/*
    ettercap -- inet utilities -- Module for Windows 9x NT/2000/XP  (cygwin)

    Copyright (C) 2001  ALoR <alor@users.sourceforge.net>, NaGA <crwm@freemail.it>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

    $Id: ec_inet_cygwin.c,v 1.17 2002/05/23 16:10:36 alor Exp $
*/

#include "../../include/ec_main.h"

#include "../../include/ec_thread.h"
#include "../../include/ec_buffer.h"
#include "../../include/ec_inet.h"
#include "../../include/ec_inet_forge.h"
#include "../../include/ec_inet_structures.h"


#include <ctype.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#include <windowsx.h>
#include <ws2tcpip.h>
#include <Iphlpapi.h>
#include <Packet32.h>
#include <Ntddndis.h>

int IpForward_status;      // old ipforward status

struct adapter {
   char  name[64];
   char  *desc;
   struct s {
      LPADAPTER lpAdapter;
      LPPACKET lpPacket;
   } send ;
   struct r {
      LPADAPTER lpAdapter;
      LPPACKET lpPacket;
   } recv ;
};

static char ETH_BROADCAST[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
static char ARP_BROADCAST[6] = {0x0,0x0,0x0,0x0,0x0,0x0};

#define ARP_TIMEOUT 0.01

struct adapter lpa;

int SocketBuffer = -1;

// protos...

int Inet_FindIFace(char *iface);
int Inet_CorrectIface(char *iface);
int Inet_GetIfaceInfo(char *iface, int *MTU, char *MyMAC, u_long *IP, u_long *NetMask);
int Inet_SetPromisc(char *iface);
int Inet_OpenRawSock(char *iface);
void Inet_CloseRawSock(int sock);
int Inet_GetRawPacket(int sock, char *buffer, int MTU, short *type);
int Inet_SendRawPacket(int sock, char *buffer, int len);
void Inet_SetNonBlock(int sock);
void Inet_Restore_ifr(void);
void Inet_DisableForwarding(void);
void Inet_RestoreForwarding(void);
char *Inet_MacFromIP(unsigned long ip);

int _Inet_OpenAdapter(char *name);
void _Inet_CloseAdapter(void);
ULONG inet_addrU(const WCHAR *cp);
HRESULT SendARP_(unsigned long DIP, unsigned long SIP, PULONG pMAC, PULONG ulen);
int get_ARP_res(PULONG recv_MAC,char *MyMAC);

// ----------------------------------------------


ULONG inet_addrU(const WCHAR *cp)
{
   ULONG val, part;
   WCHAR c;
   int i;

   val = 0;
   for (i = 0; i < 4; i++) {
      part = 0;
      while ((c = *cp++) != '\0' && c != '.') {
         if (c < '0' || c > '9')
            return -1;
         part = part*10 + (c - '0');
      }
      if (part > 255)
         return -1;
      val = (val << 8) | part;
      if (i == 3) {
         if (c != '\0')
            return -1;  // extra gunk at end of string
      } else {
         if (c == '\0')
            return -1;  // string ends early
      }
   }
   return val;
}

int get_ARP_res(PULONG recv_MAC,char *MyMAC)
{
   char *buf,*c_raw;
   unsigned long l_buf;
   unsigned long off,d_len;
   struct bpf_hdr  *pdata;
   ETH_header *ethpkt;
   ARP_header *arppkt;

   off = 0;
   PacketReceivePacket(lpa.recv.lpAdapter,lpa.recv.lpPacket,TRUE);
   if ( (!lpa.recv.lpPacket) || ((l_buf = lpa.recv.lpPacket->ulBytesReceived)==0) ) return 0;
   buf = lpa.recv.lpPacket->Buffer;

   while (off<l_buf) {
      pdata = (struct bpf_hdr *)(buf+off);
      d_len = pdata->bh_datalen;
      off += pdata->bh_hdrlen;
      c_raw = (char *)(buf+off);

      ethpkt = (ETH_header *)c_raw;
      arppkt = (ARP_header *)(c_raw + ETH_HEADER);

      off = Packet_WORDALIGN(off+d_len);

      if (( ntohs(ethpkt->type)==ETH_P_ARP) &&  ( ntohs(arppkt->opcode)==ARPOP_REPLY) &&
            ( memcmp(&(ethpkt->source_mac), &MyMAC,6) )) {
         memcpy(recv_MAC, &(arppkt->source_add),6 ) ;
         return 1;
      }
   }
   return 0;
}


HRESULT SendARP_(unsigned long DIP, unsigned long SIP, PULONG pMAC, PULONG ulen)
{
   u_char *buf;
   static char MyMAC[6] = "";
   int MTU, ok = 0;
   TIME_DECLARE;

   memset(pMAC,0,6);
   if (!strcmp(MyMAC, ""))
      Inet_GetIfaceInfo(NULL, &MTU, MyMAC, NULL, NULL);

   buf = Inet_Forge_packet( ETH_HEADER + ARP_HEADER );
   Inet_Forge_ethernet( buf, MyMAC, ETH_BROADCAST, ETH_P_ARP );
   Inet_Forge_arp( buf+ETH_HEADER, ARPOP_REQUEST, MyMAC, SIP, ARP_BROADCAST, DIP );

   PacketSetHwFilter(lpa.recv.lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS);
   Inet_SendRawPacket(0, buf, ETH_HEADER + ARP_HEADER);

   TIME_START;
   while (!get_ARP_res(pMAC,MyMAC)) {
     TIME_FINISH;
     if (TIME_ELAPSED >= ARP_TIMEOUT) ok = 1;
     if (ok) break;
   }

   PacketSetHwFilter(lpa.recv.lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL);
   Inet_Forge_packet_destroy( buf );

   *ulen = 6;

   return ok;
}

int _Inet_OpenAdapter(char *name)
{
   u_char *buffer;
   NetType medium;

   DEBUG_MSG("_Inet_OpenAdapter");

   if ((lpa.recv.lpAdapter = PacketOpenAdapter(name)) == NULL || lpa.recv.lpAdapter->hFile == INVALID_HANDLE_VALUE)
      Error_msg("Can not open [%s]", name);

   if (!PacketGetNetType(lpa.recv.lpAdapter, &medium))
      ERROR_MSG("PacketGetNetType()");

   switch (medium.LinkType) {
      case NdisMedium802_3:
                           break;
      default:
         Error_msg("Device type not supported");
   }

   if ((lpa.send.lpAdapter = PacketOpenAdapter(name)) == NULL || lpa.send.lpAdapter->hFile == INVALID_HANDLE_VALUE)
      Error_msg("Can not open [%s]", name);

   buffer = (u_char *)malloc(256000);
   if (buffer == NULL) {
      ERROR_MSG("malloc()");
   }

   /* allocate packet structure used during the capture */
   if((lpa.recv.lpPacket = PacketAllocatePacket()) == NULL)
      ERROR_MSG("Failed to allocate the LPPACKET structure.");

   PacketInitPacket(lpa.recv.lpPacket, (BYTE*)buffer, 256000);

   DEBUG_MSG("_Inet_OpenAdapter -- PacketInitPacket 256000");

   /* allocate the standard buffer in the driver */
   if(PacketSetBuff(lpa.recv.lpAdapter, 512000) == FALSE)
      ERROR_MSG("not enough memory to allocate the buffer\n");

   PacketSetMinToCopy(lpa.recv.lpAdapter, 40);

   PacketSetReadTimeout(lpa.recv.lpAdapter, 1);

   atexit(_Inet_CloseAdapter);

   return 0;
}



void _Inet_CloseAdapter(void)
{
   DEBUG_MSG("_Inet_CloseAdapter");

   PacketFreePacket(lpa.recv.lpPacket);
   PacketCloseAdapter(lpa.recv.lpAdapter);
   PacketCloseAdapter(lpa.send.lpAdapter);

}



int Inet_FindIFace(char *iface)     // adapded from eth-win32.c part of libdnet  copyright Dug Song
{
   struct adapter alist[16];
#ifdef WIN9X
   CHAR *name, wbuf[2048];
#else
   WCHAR *name, wbuf[2048];
#endif
   ULONG wlen;
   char *desc;
   int i, j, k, alen, max = -1;
   char devstr[3];
   int dev = 0;

   DEBUG_MSG("Inet_FindIFace");

   memset(devstr, 0, sizeof(devstr));
   memset(alist, 0, sizeof(alist));

   alen = sizeof(alist) / sizeof(alist[0]);
   wlen = sizeof(wbuf) / sizeof(wbuf[0]);

   if (!PacketGetAdapterNames((char *)wbuf, &wlen))
      ERROR_MSG("PacketGetAdapterNames()");

   for (name = wbuf, i = 0; *name != '\0' && i < alen; i++) {
#ifdef WIN9X
      strncpy(alist[i].name, name, sizeof(alist[0].name));
#else
      wcstombs(alist[i].name, name, sizeof(alist[0].name));
#endif
      while (*name++ != '\0')
         ;
   }

#ifdef WIN9X
   for (desc = (char *)name + 1, j = 0; *desc != '\0' && j < alen; j++) {
#else
   for (desc = (char *)name + 2, j = 0; *desc != '\0' && j < alen; j++) {
#endif
      alist[j].desc = desc;
      while (*desc++ != '\0')
         ;
   }

   printf("List of available devices :\n\n");

   for (i = 0; i < j; i++) {
      if (!strlen(alist[i].name)) continue;
      if (!strcmp(alist[i].name, "\\Device\\Packet_NdisWanIp")) continue;  // remove the WanAdapter from the list
      for(k = 0; k<strlen(alist[i].desc); k++)
         if (alist[i].desc[k] == ' ' && (alist[i].desc[k+1] == ' ' || alist[i].desc[k+1] == '(' )) { // trim parentheses from microsoft packet scheduler
            alist[i].desc[k] = 0;
            break;
         }
      DEBUG_MSG("  --> [dev%d] - [%s]", i, alist[i].desc);
      printf("  --> [dev%d] - [%s]\n", i, alist[i].desc);
      max = i;
   }

   if (max == -1) return -1;

   printf("\n\nPlease select one of the above, which one ? [0]: ");
   fflush(stdout);
   i = 0;
   while ( i < 2 && (devstr[i] = (char) getchar()) && devstr[i++] != '\n' );
   //scanf("%d", &dev);
   dev = atoi(devstr);

   if (dev > max)
      Error_msg("Please select a device between 0 and %d", max);

   DEBUG_MSG("  --> User has selected [dev%d] of %d", dev, max);

   sprintf(iface, "dev%d", dev);

   return(Inet_CorrectIface(iface));

}


int Inet_CorrectIface(char *iface)
{
   struct adapter alist[16];
#ifdef WIN9X
   CHAR *name, wbuf[2048];
#else
   WCHAR *name, wbuf[2048];
#endif
   ULONG wlen;
   char *desc;
   int i, j, k, alen;
   int dev = 0;

   DEBUG_MSG("Inet_CorrectIface -- [%s]", iface);

   if (!strcmp(iface, "list"))    // easter egg : to get a list of interface with device name
      printf("List of available devices :\n\n");
   else if (sscanf(iface, "dev%d", &dev) != 1)
         Error_msg("Incorrect device string (the format is \"dev[n]\")");

   memset(alist, 0, sizeof(alist));

   alen = sizeof(alist) / sizeof(alist[0]);
   wlen = sizeof(wbuf) / sizeof(wbuf[0]);

   if (!PacketGetAdapterNames((char *)wbuf, &wlen))
      ERROR_MSG("PacketGetAdapterNames()");

   for (name = wbuf, i = 0; *name != '\0' && i < alen; i++) {
#ifdef WIN9X
      strncpy(alist[i].name, name, sizeof(alist[0].name));
#else
      wcstombs(alist[i].name, name, sizeof(alist[0].name));
#endif
      while (*name++ != '\0')
         ;
   }

#ifdef WIN9X
   for (desc = (char *)name + 1, j = 0; *desc != '\0' && j < alen; j++) {
#else
   for (desc = (char *)name + 2, j = 0; *desc != '\0' && j < alen; j++) {
#endif
      alist[j].desc = desc;
      while (*desc++ != '\0')
         ;
   }

   for (i = 0; i < j; i++) {
      if (!strlen(alist[i].name)) continue;
      if (strcmp(iface, "list") && !strcmp(alist[i].name, "\\Device\\Packet_NdisWanIp")) continue;  // remove the WanAdapter from the list
      for(k = 0; k<strlen(alist[i].desc); k++)
         if (alist[i].desc[k] == ' ' && (alist[i].desc[k+1] == ' ' || alist[i].desc[k+1] == '(' )) { // trim parentheses from microsoft packet scheduler
            alist[i].desc[k] = 0;
            break;
         }
      DEBUG_MSG("  --> [dev%d] - [%s]", i, alist[i].desc);
      if (strcmp(iface, "list")) {
         if (dev == i) break;
      } else {
         printf("  --> [dev%d] - [%s]\n               [%s]\n", i, alist[i].desc, alist[i].name);
      }
   }
   if (!strcmp(iface, "list")) exit(0);

   if (i == j) return -1;

   DEBUG_MSG("Inet_CorrectIface -- [%d] [%d] [%d]", dev, i, j);

   _Inet_OpenAdapter(alist[dev].name);

   sprintf(lpa.name, alist[dev].name);
   sprintf(lpa.desc, alist[dev].desc);

   return 0;
}



int Inet_GetIfaceInfo(char *iface, int *MTU, char *MyMAC, unsigned long *IP, unsigned long *NetMask)
{
#ifdef WIN9X
   PIP_ADAPTER_INFO pinfo=NULL;
   u_long len = 0;
#endif

   if (MTU != NULL)  *MTU = 1500; // XXX -- it is better to find the real one...

   if (MyMAC != NULL) {
      PACKET_OID_DATA *data;
      u_char buf[512];

      data = (PACKET_OID_DATA *)buf;
      data->Oid = OID_802_3_CURRENT_ADDRESS;
      data->Length = 6;

      if (PacketRequest(lpa.recv.lpAdapter, FALSE, data) == TRUE) {
         memcpy(MyMAC, data->Data, 6);
      }
   }

   if (IP != NULL) {
#ifdef WIN9X
      len = sizeof(IP_ADAPTER_INFO);
      pinfo = (PIP_ADAPTER_INFO)malloc(len);
      GetAdaptersInfo(pinfo,&len);
      *IP = inet_addr(pinfo->IpAddressList.IpAddress.String);
#else
      u_long foo;
      PacketGetNetInfo(lpa.name, IP, &foo);
      *IP = ntohl(*IP);
#endif

      if (*IP == 0) {
         HKEY  ServicesKey;
         HKEY  InterfaceKey;
         HKEY  TcpIpKey;
         WCHAR String[32];
         ULONG BufLen;
         DWORD RegType;
         DWORD DHCPEnabled;
         char *clsid = strdup(strchr(lpa.name, '_') + 1);

         DEBUG_MSG("Inet_GetIfaceInfo -- try to correct DHCP bug of PacketGetNetInfo()");

         RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services"), 0, KEY_READ, &ServicesKey);
         RegOpenKeyEx(ServicesKey, clsid, 0, KEY_READ, &InterfaceKey);
         free(clsid);
         RegOpenKeyEx(InterfaceKey, TEXT("Parameters\\TcpIp"), 0, KEY_READ, &TcpIpKey);
         BufLen = sizeof(DHCPEnabled);
         RegQueryValueEx(TcpIpKey, TEXT("EnableDHCP"), NULL, &RegType, (LPBYTE)&DHCPEnabled, &BufLen);

         if (DHCPEnabled) {
            BufLen = sizeof(String);
            RegQueryValueEx(TcpIpKey,TEXT("DHCPIPAddress"), NULL, &RegType, (LPBYTE)String, &BufLen);

            *IP = inet_addr((char *)String);

            DEBUG_MSG("Inet_GetIfaceInfo -- DHCP bug recovered with %s", inet_ntoa(*(struct in_addr *)IP));

         } else {
            Error_msg("The Adapter has an invalid ip address");
         }
      }
   }

   if (NetMask != NULL) {
#ifdef WIN9X
      if (pinfo==NULL) {
         len = sizeof(IP_ADAPTER_INFO);
         pinfo = (PIP_ADAPTER_INFO)malloc(len);
         GetAdaptersInfo(pinfo,&len);
      }
      *NetMask = inet_addr(pinfo->IpAddressList.IpMask.String);
#else
       u_long foo;
       PacketGetNetInfo(lpa.name, &foo, NetMask);
       *NetMask = ntohl(*NetMask);
#endif

      if (strcmp(Options.netmask, ""))       // specified on command line
         *NetMask = inet_addr(Options.netmask);

   }

#ifdef WIN9X
   if (pinfo != NULL) free(pinfo);
#endif

   return 0;
}



void Inet_SetNonBlock(int sock)
{
   DEBUG_MSG("Inet_SetNonBlock fd = %d", sock);

   fcntl(sock, F_SETFL, O_NONBLOCK);

}



void Inet_CloseRawSock(int sock)
{

   DEBUG_MSG("Inet_CloseRawSock \t wrappered to /dev/NULL");

   close(sock);

}




int Inet_OpenRawSock(char *iface)
{

   DEBUG_MSG("Inet_OpenRawSock \t WRAPPERED TO /dev/NULL");

   return open("/dev/null", O_RDONLY, 0600 );
}



int Inet_GetRawPacket(int sock, char *buffer, int MTU, short *type)
{

   int len = 0, pktlen = 0;
   u_char *bp, *ep;
   static char MyMAC[6]={0x65,0x74,0x74,0x65,0x72,0x63};

   if (SocketBuffer == -1)                   // only the first time
   {
      SocketBuffer = Buffer_Create(1.0e5);   // 100 K buffer
      DEBUG_MSG("Inet_GetRawPacket creates the buffer for the first time -- buf id = %d", SocketBuffer);
   }

   Buffer_Get(SocketBuffer, &pktlen, sizeof(u_int));
   len = Buffer_Get(SocketBuffer, buffer, pktlen );

   if (type != NULL)
   {
       if (!strncmp(MyMAC,"etterc",6))    // only the first time...
           Inet_GetIfaceInfo(Options.netiface, NULL, MyMAC, NULL, NULL);
       if (!memcmp(MyMAC,buffer,6))
           *type = PACKET_HOST;
       else
           *type = !PACKET_HOST;
   }

   if (len > 0) return len;                     // there was pending fata.


//   DEBUG_MSG("Inet_GetRawPacket -- pre Receive" );

   PacketReceivePacket(lpa.recv.lpAdapter, lpa.recv.lpPacket, TRUE);

   len = lpa.recv.lpPacket->ulBytesReceived;

//   DEBUG_MSG("Inet_GetRawPacket -- after receive %d", len );

   bp = lpa.recv.lpPacket->Buffer;

   /*
    * Loop through each packet.
    */

#define bhp ((struct bpf_hdr *)bp)
   ep = bp + len;
   while (bp < ep) {
      int caplen, hdrlen;
      caplen = bhp->bh_caplen;
      hdrlen = bhp->bh_hdrlen;

      Buffer_Put(SocketBuffer, &caplen, sizeof(u_int) );
      Buffer_Put(SocketBuffer, bp + hdrlen, caplen );

      bp += Packet_WORDALIGN(caplen + hdrlen);
   }
#undef bhp

   Buffer_Get(SocketBuffer, &pktlen, sizeof(u_int));
   len = Buffer_Get(SocketBuffer, buffer, pktlen );

   if (type != NULL)
   {
      if (!memcmp(MyMAC,buffer,6))
           *type = PACKET_HOST;
       else
           *type = !PACKET_HOST;
   }

   return len;
}



int Inet_SendRawPacket(int sock, char *buffer, int len)
{
   LPPACKET lpPacket;

   if( (lpPacket = PacketAllocatePacket()) == NULL)
      ERROR_MSG("Failed to allocate the LPPACKET structure.");

   PacketInitPacket(lpPacket, buffer, len);

//   DEBUG_MSG("I'm going to send %d bytes", len);

   if ( PacketSendPacket(lpa.send.lpAdapter, lpPacket, TRUE) == FALSE)
      ERROR_MSG("Failed to write to the adapter");

//   DEBUG_MSG(" %d bytes sent", len);

   PacketFreePacket(lpPacket);

   return (len);
}



int Inet_SetPromisc(char *iface)
{
   DEBUG_MSG("Inet_SetPromisc");

   PacketSetHwFilter(lpa.recv.lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS);

   atexit(Inet_Restore_ifr);

   return 0;
}



void Inet_Restore_ifr(void)
{
   DEBUG_MSG("Inet_Restore_ifr");

   PacketSetHwFilter(lpa.recv.lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL);

}



void Inet_DisableForwarding(void)
{
   HKEY       IpForwardKey;
   long       Status;
#ifdef WIN9X
   DWORD      dim = 2;
   char       IpForwardSz[2];
#else
   DWORD      dim = 4;
#endif
   DWORD      value = 3;


   Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
#ifdef WIN9X
                         TEXT("SYSTEM\\CurrentControlSet\\Services\\VxD\\Mstcp"),
#else
                         TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
#endif
                         0,
                         KEY_READ|KEY_SET_VALUE,
                         &IpForwardKey);

#ifdef WIN9X
   Status = RegQueryValueEx(IpForwardKey, TEXT("EnableRouting"), NULL, NULL, (LPBYTE)IpForwardSz, &dim);
   value = IpForwardSz[0]-'0';
#else
   Status = RegQueryValueEx(IpForwardKey, TEXT("IPEnableRouter"), NULL, NULL, (LPBYTE)&value, &dim);
#endif

   DEBUG_MSG("Inet_DisableForwarding -- previous value %d", value);

   if (value == 0) {
      RegCloseKey(IpForwardKey);
      return;  // this is ok and don't need to be changed
   }

   IpForward_status = value;
   atexit(Inet_RestoreForwarding);

   value = 0;

#ifdef WIN9X
   IpForwardSz[0]=value+'0';
   IpForwardSz[1]='\0';
   Status = RegSetValueEx(IpForwardKey, TEXT("EnableRouting"), 0, REG_SZ, (LPBYTE)IpForwardSz, dim);
#else
   Status = RegSetValueEx(IpForwardKey, TEXT("IPEnableRouter"), 0, REG_DWORD, (LPBYTE)&value, dim);
#endif

   if (Status != 0) {
      fprintf(stderr, "\n\nRegSetValueEx() | ERROR %ld\n\n", Status);
      fprintf(stderr, "Please manually disable ip forwarding\n");
#ifdef WIN9X
      fprintf(stderr, "set to 0 the HKLM\\SYSTEM\\CurrentControlSet\\Services\\VxD\\Mstcp\\EnableRouting\n\n");
#else
      fprintf(stderr, "set to 0 the HKLM\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\IPEnableRouter\n\n");
#endif
      exit(-1);
   }

   RegCloseKey(IpForwardKey);

}



void Inet_RestoreForwarding(void)
{
   HKEY       IpForwardKey;
#ifdef WIN9X
   DWORD      dim = 2;
   char       IpForwardSz[2];
#else
   DWORD      dim = 4;
#endif


   RegOpenKeyEx(HKEY_LOCAL_MACHINE,
#ifdef WIN9X
                TEXT("SYSTEM\\CurrentControlSet\\Services\\VxD\\Mstcp"),
#else
                TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
#endif
                0,
                KEY_READ|KEY_SET_VALUE,
                &IpForwardKey);

#ifdef WIN9X
   IpForwardSz[0]=IpForward_status+'0';
   IpForwardSz[1]='\0';
   RegSetValueEx(IpForwardKey, TEXT("EnableRouting"), 0, REG_SZ, (LPBYTE)IpForwardSz, dim);
#else
   RegSetValueEx(IpForwardKey, TEXT("IPEnableRouter"), 0, REG_DWORD, (LPBYTE)&IpForward_status, dim);
#endif

   DEBUG_MSG("Inet_RestoreForwarding -- new value %d", IpForward_status);

   RegCloseKey(IpForwardKey);

}


char *Inet_MacFromIP(unsigned long ip)
{
   HRESULT hr;
   static char mac[6];
   ULONG   ulLen;

   memset (mac, 0xff, sizeof(mac));
   ulLen = 6;

   hr = SendARP_(ip, 0, (PULONG)mac, &ulLen);

#ifdef DEBUG
   {
      char mac_string[17];
      Inet_PutMACinString(mac_string, mac);
      DEBUG_MSG("Inet_MacFromIP -- %s \t%s", inet_ntoa(*(struct in_addr *)&ip), mac_string);
   }
#endif

   return mac;
}


/* EOF */

// vim:ts=3:expandtab

