/*
 * This file was generated automatically by ExtUtils::ParseXS version 2.18 from the
 * contents of ARP.xs. Do not edit this file, edit ARP.xs instead.
 *
 *	ANY CHANGES MADE HERE WILL BE LOST! 
 *
 */

#line 1 "ARP.xs"
/*
Perl ARP Extension
Create and send an arp packets, lookup mac addresses

Programmed by Bastian Ballmann
Last update: 31.01.2007

This program is free software; you can redistribute 
it and/or modify it under the terms of the 
GNU General Public License version 2 as published 
by the Free Software Foundation.

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. 
*/

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"
#include <stdio.h>           
#include <stdlib.h>          
#include <string.h>          
#include <errno.h>           
#include <net/ethernet.h>    
#include <net/if.h>
#include <arpa/inet.h>       
#include "arp.h"

#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#line 48 "ARP.c"

XS(XS_Net__ARP_send_packet); /* prototype to pass -Wmissing-prototypes */
XS(XS_Net__ARP_send_packet)
{
#ifdef dVAR
    dVAR; dXSARGS;
#else
    dXSARGS;
#endif
    if (items != 6)
       Perl_croak(aTHX_ "Usage: %s(%s)", "Net::ARP::send_packet", "dev, sip, dip, smac, dmac, type");
    PERL_UNUSED_VAR(cv); /* -W */
    {
	unsigned char *	dev = (unsigned char *)SvPV_nolen(ST(0));
	unsigned char *	sip = (unsigned char *)SvPV_nolen(ST(1));
	unsigned char *	dip = (unsigned char *)SvPV_nolen(ST(2));
	unsigned char *	smac = (unsigned char *)SvPV_nolen(ST(3));
	unsigned char *	dmac = (unsigned char *)SvPV_nolen(ST(4));
	unsigned char *	type = (unsigned char *)SvPV_nolen(ST(5));
	int	RETVAL;
	dXSTARG;
#line 46 "ARP.xs"
	  int uid;
	  unsigned int packetsize = sizeof(struct arphdr) + sizeof(struct ether_header);
	  unsigned char packet[packetsize];
	  struct ether_header *ethhdr = (struct ether_header *)packet;
	  struct arphdr *arp = (struct arphdr *)(packet + sizeof(struct ether_header));
	  u_short op;	

          RETVAL = 1;

	  // Are you root?
	  uid = getuid();
	  if(uid != 0) 
	  { 
	    printf("You must have UID 0 instead of %d.\n",uid); 
	    exit(0);
	  }

	  // Initialize packet buffer 
	  memset(packet,0,packetsize);

	  // What's the ARP operation type?
	  if(!strcmp(type,"request"))
	  {
	    op = ARPOP_REQUEST;
	  }
	  else if(!strcmp(type,"reply"))
	  {
	    op = ARPOP_REPLY;
	  }
	  else if(!strcmp(type,"revrequest"))
	  {
	    op = ARPOP_REVREQUEST;
	  }
	  else if(!strcmp(type,"revreply"))
	  {
	    op = ARPOP_REVREPLY;
	  }
	  else if(!strcmp(type,"invrequest"))
	  {
	    op = ARPOP_INVREQUEST;
	  }
	  else if(!strcmp(type,"invreply"))
	  {
	    op = ARPOP_INVREPLY;
	  }
	  else
	  {
	    op = ARPOP_REPLY;
	  }

	  if(smac == NULL)
	  {
	    printf("Parameter smac is NULL! Terminating.\n");
	    RETVAL = 0;
	  }

	  if(dmac == NULL)
	  {
	    printf("Parameter dmac is NULL! Terminating.\n");
	    RETVAL = 0;
	  }

          // Found a dollar sign?
	  if(strchr(smac,36))
	  {
	    printf("Found a $ char in smac! Terminating.\n");
	    RETVAL = 0;
	  }

	  if(strchr(dmac,36))
	  {
	    printf("Found a $ char in dmac! Terminating.\n");
	    RETVAL = 0;
	  }

          if(ether_aton(smac) == NULL)
          {
            printf("Invalid source mac address! Terminating.\n");
            RETVAL = 0;
          }

          if(ether_aton(dmac) == NULL)
          {
            printf("Invalid destination mac address! Terminating.\n");
            RETVAL = 0;
          }

          // Check ips
          if(inet_addr(sip) == INADDR_NONE)
          {
            printf("Invalid source ip address! Terminating.\n");
            RETVAL = 0;
          }

          if(inet_addr(dip) == INADDR_NONE)
          {
            printf("Invalid destination ip address! Terminating.\n");
            RETVAL = 0;
          }

          // Construct and send packet
          if(RETVAL != 0)
          {
	  	// Ethernet header
	        memcpy(ethhdr->ether_dhost,(u_char *)ether_aton(dmac),ETHER_ADDR_LEN); // Destination MAC
	        memcpy(ethhdr->ether_shost,(u_char *)ether_aton(smac),ETHER_ADDR_LEN); // Source MAC
	        ethhdr->ether_type = htons(ETHERTYPE_ARP);                             // ARP protocol

	        // ARP header
	        arp->hw_type = htons(ARPHDR_ETHER);                                    // Hardware address type
	        arp->proto_type = htons(ETH_P_IP);                                     // Protocol address type
	        arp->ha_len = ETH_ALEN;                                                // Hardware address length
	        arp->pa_len = IP_ALEN;                                                 // Protocol address length
	        arp->opcode = htons(op);                                               // ARP operation
	        memcpy(arp->source_add,(u_char *)ether_aton(smac),ETH_ALEN);           // Source MAC
	        *(u_long *)arp->source_ip = inet_addr(sip);                            // Source IP

	        if(strcmp(dmac,"ff:ff:ff:ff:ff:ff"))
          		memcpy(arp->dest_add,(u_char *)ether_aton(dmac),ETH_ALEN);       // Destination MAC

	         *(u_long *)arp->dest_ip = inet_addr(dip);                              // Destination IP


	         // Run packet!! Run!
	         // FreeBSD code
	         if(SOCK_TYPE == SOCK_RAW)
	         {
	           RETVAL = send_packet_bsd(dev,packet,packetsize);	
	         }

	         // Linux code
	         else
	         {
	           RETVAL = send_packet_linux(dev,packet,packetsize);
	         }
          }

#line 208 "ARP.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS(XS_Net__ARP_get_mac); /* prototype to pass -Wmissing-prototypes */
XS(XS_Net__ARP_get_mac)
{
#ifdef dVAR
    dVAR; dXSARGS;
#else
    dXSARGS;
#endif
    if (items != 1)
       Perl_croak(aTHX_ "Usage: %s(%s)", "Net::ARP::get_mac", "dev");
    PERL_UNUSED_VAR(cv); /* -W */
    {
	unsigned char *	dev = (unsigned char *)SvPV_nolen(ST(0));
	char *	RETVAL;
	dXSTARG;
#line 191 "ARP.xs"
          char tmp[20] = "unknown";

	  if(SOCK_TYPE == SOCK_RAW)
	  {
	    get_mac_bsd(dev,tmp);
	  }
	  else
	  {
	    get_mac_linux(dev,tmp);
	  }

	  RETVAL = tmp;

#line 244 "ARP.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS(XS_Net__ARP_arp_lookup); /* prototype to pass -Wmissing-prototypes */
XS(XS_Net__ARP_arp_lookup)
{
#ifdef dVAR
    dVAR; dXSARGS;
#else
    dXSARGS;
#endif
    if (items != 2)
       Perl_croak(aTHX_ "Usage: %s(%s)", "Net::ARP::arp_lookup", "dev, ip");
    PERL_UNUSED_VAR(cv); /* -W */
    {
	unsigned char *	dev = (unsigned char *)SvPV_nolen(ST(0));
	unsigned char *	ip = (unsigned char *)SvPV_nolen(ST(1));
	char *	RETVAL;
	dXSTARG;
#line 214 "ARP.xs"
	  char tmp[20] = "unknown";

	  if(SOCK_TYPE == SOCK_RAW)
	  {
	    arp_lookup_bsd(dev,ip,tmp);
	  }
	  else
	  {
	    arp_lookup_linux(dev,ip,tmp);
	  }

	  RETVAL = tmp;

#line 281 "ARP.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C"
#endif
XS(boot_Net__ARP); /* prototype to pass -Wmissing-prototypes */
XS(boot_Net__ARP)
{
#ifdef dVAR
    dVAR; dXSARGS;
#else
    dXSARGS;
#endif
    char* file = __FILE__;

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
    XS_VERSION_BOOTCHECK ;

        newXS("Net::ARP::send_packet", XS_Net__ARP_send_packet, file);
        newXS("Net::ARP::get_mac", XS_Net__ARP_get_mac, file);
        newXS("Net::ARP::arp_lookup", XS_Net__ARP_arp_lookup, file);
    XSRETURN_YES;
}



syntax highlighted by Code2HTML, v. 0.9.1