1: #include <stdlib.h> 
     2: #include <sys/socket.h> 
     3: #include <netinet/in.h> 
     4: #include <arpa/inet.h> 
     5: 
     6: #include <linux/sockios.h> 
     7: #include <sys/file.h> 
     8: #include <sys/time.h> 
     9: #include <sys/signal.h> 
    10: #include <sys/ioctl.h> 
    11: #include <linux/if.h> 
    12: #include <linux/if_arp.h> 
    13: #include <sys/uio.h> 
    14: 
    15: #include <unistd.h> 
    16: #include <stdio.h> 
    17: #include <ctype.h> 
    18: #include <errno.h> 
    19: #include <string.h> 
    20: 
    21: #define MAX_SEND        4 
    22: #define MAX_RECV        3 
    23: #define RESP_TIMEOUT    20  // time in usec to wait for response 
    24: 
    25: ///////////////////////////////////////////////////////////////////////////////
    26: // Class can be used for creating and receiving arp packets.
    27: ///////////////////////////////////////////////////////////////////////////////
    28: class CArpTest
    29: {
    30: public:
    31:     /////////////////////////////////////////////////////////////////////////////
    32:     //  
    33:     //
    34:     ///////////////////////////////////////////////////////////////////////////////
    35:     CArpTest::CArpTest( const char * const device = "eth0" ) : m_arp_socket( -1 ), m_dev( device )
    36:         {
    37:         initSocket();
    38:         };
    39:     /////////////////////////////////////////////////////////////////////////////
    40:     //
    41:     //
    42:     /////////////////////////////////////////////////////////////////////////////
    43:     CArpTest::~CArpTest()
    44:         {
    45:         close( m_arp_socket );
    46:         };
    47: 
    48: private:
    49:     int m_arp_socket;
    50:     const char * const m_dev;
    51:     struct sockaddr_ll  m_slladdr;
    52:     struct sockaddr_ll  m_dlladdr;
    53:     
    54:     /////////////////////////////////////////////////////////////////////////////
    55:     //
    56:     // Set up socket
    57:     //
    58:     ///////////////////////////////////////////////////////////////////////////////
    59:     void initSocket()
    60:         {
    61:         
    62:         if ( ( m_arp_socket = socket( PF_PACKET, SOCK_DGRAM, 0 ) ) < 0 ) 
    63:             {
    64:             printf( "Error: the socket() call retured %d: %s\n", m_arp_socket, strerror(errno) );
    65:             exit( 1 );
    66:             }
    67:         
    68:         // Set nonblocking flag
    69:         int val = 1;
    70:         if ( ioctl( m_arp_socket, FIONBIO, &val ) < 0 ) 
    71:             {
    72:             printf( "Error: FIONBIO: %s\n", strerror(errno) );
    73:             close( m_arp_socket );
    74:             exit ( 1 );
    75:             }
    76:     
    77:         struct ifreq ifr;
    78:         memset( &ifr, 0, sizeof(ifr) );
    79:         strncpy( ifr.ifr_name, m_dev, IFNAMSIZ-1 );
    80:         if ( ioctl( m_arp_socket, SIOCGIFINDEX, &ifr ) < 0 ) 
    81:             {
    82:             printf( "Error: SIOCGIFINDEX: %s\n", strerror(errno) );
    83:             close( m_arp_socket );
    84:             exit( 1 );
    85:             }
    86:             
    87:         // Bind socket
    88:         m_slladdr.sll_family    = AF_PACKET;
    89:         m_slladdr.sll_ifindex   = ifr.ifr_ifindex;
    90:         m_slladdr.sll_protocol  = htons( ETH_P_ARP );
    91:         if ( bind( m_arp_socket, (struct sockaddr*) &m_slladdr, sizeof(m_slladdr) ) == -1 ) 
    92:             {
    93:             printf( "Error in bind() call: %s\n", strerror(errno) );
    94:             close( m_arp_socket );
    95:             exit( 1 );
    96:             }
    97: 
    98:         unsigned int len = sizeof(m_slladdr);
    99:         if ( getsockname( m_arp_socket, (struct sockaddr*) &m_slladdr, &len ) < 0 ) 
   100:             {
   101:             printf( "Error in getsockname() call: %s\n", strerror(errno) );
   102:             close( m_arp_socket );
   103:             exit( 1 );
   104:             }
   105: 
   106:         if ( m_slladdr.sll_halen == 0 ) 
   107:             {
   108:             close( m_arp_socket );
   109:             exit( 1 );
   110:             }
   111: 
   112:         m_dlladdr = m_slladdr;
   113:         memset( m_dlladdr.sll_addr, -1,  m_dlladdr.sll_halen);
   114:         }
   115:     /////////////////////////////////////////////////////////////////////////////
   116:     //
   117:     // Send out an arp packet
   118:     //
   119:     ///////////////////////////////////////////////////////////////////////////////
   120:     int send_pack(  int socket, 
   121:                             struct in_addr src, 
   122:                             struct in_addr dst,
   123:                             struct sockaddr_ll *ME, 
   124:                             struct sockaddr_ll *HE, 
   125:                             int advert = 0 )        
   126:         {
   127:         unsigned char buf[256] = {0};
   128:         struct arphdr *ah = (struct arphdr*)buf;
   129:         unsigned char *p = (unsigned char *)(ah+1);
   130: 
   131:         ah->ar_hrd = htons(ME->sll_hatype);
   132:         if (ah->ar_hrd == htons(ARPHRD_FDDI))
   133:             {
   134:             ah->ar_hrd = htons(ARPHRD_ETHER);
   135:             }
   136:             
   137:         ah->ar_pro = htons(ETH_P_IP);
   138:         ah->ar_hln = ME->sll_halen;
   139:         ah->ar_pln = 4;
   140:         ah->ar_op  = ( advert ? htons(ARPOP_REPLY) : htons(ARPOP_REQUEST) );
   141: 
   142:         memcpy( p, &ME->sll_addr, ah->ar_hln );
   143:         p += ME->sll_halen;
   144: 
   145:         memcpy( p, &src, 4 );
   146:         p += 4;
   147: 
   148:         if ( advert )
   149:             {
   150:             memcpy( p, &ME->sll_addr, ah->ar_hln );
   151:             }
   152:         else
   153:             {
   154:             memcpy( p, &HE->sll_addr, ah->ar_hln );
   155:             }
   156:             
   157:         p+=ah->ar_hln;
   158: 
   159:         memcpy( p, &dst, 4 );
   160:         p += 4;
   161: 
   162:         return sendto( socket, buf, p - buf, 0, (struct sockaddr*)HE, sizeof(*HE) );
   163:         }
   164: 
   165:     /////////////////////////////////////////////////////////////////////////////
   166:     //
   167:     // Receive arp packets
   168:     //
   169:     ///////////////////////////////////////////////////////////////////////////////
   170:     int recv_pack(  unsigned char *buf, 
   171:                     int len, 
   172:                     struct sockaddr_ll *FROM,
   173:                     struct in_addr &src_ip,
   174:                     struct in_addr &dst_ip,
   175:                     unsigned char *mac )
   176:         {
   177:         struct timeval tv;
   178:         struct arphdr *ah = (struct arphdr*)buf;
   179:         unsigned char *p = (unsigned char *)(ah+1);
   180: 
   181:         gettimeofday( &tv, NULL );
   182: 
   183:         // Filter out wild packets //
   184:         if ( FROM->sll_pkttype != PACKET_HOST &&
   185:              FROM->sll_pkttype != PACKET_BROADCAST &&
   186:              FROM->sll_pkttype != PACKET_MULTICAST )
   187:             return 0;
   188: 
   189:         // Only these types are recognised //
   190:         if ( ah->ar_op != htons(ARPOP_REPLY) ) return 0;
   191: 
   192:         // ARPHRD check and this darned FDDI hack here :-( //
   193:         if ( ah->ar_hrd != htons(FROM->sll_hatype) &&
   194:             ( (FROM->sll_hatype != ARPHRD_FDDI) || (ah->ar_hrd != htons(ARPHRD_ETHER)) ) )
   195:             {
   196:             return 0;
   197:             }
   198: 
   199:         // Protocol must be IP. //
   200:         if ( ah->ar_pro != htons(ETH_P_IP) )            return 0;
   201:         if ( ah->ar_pln != 4 )                          return 0;
   202:         if ( len < (int) (sizeof(*ah) + 2*(4 + ah->ar_hln) ))   return 0;
   203:         
   204:         memcpy( &src_ip, p+ah->ar_hln, 4 );
   205:         memcpy( &dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4 );
   206:         memcpy( mac, p, ah->ar_hln );
   207: 
   208:         return 1;
   209:         }
   210: 
   211:     /////////////////////////////////////////////////////////////////////////////
   212:     //
   213:     // Send out an arp request
   214:     //
   215:     ///////////////////////////////////////////////////////////////////////////////
   216:     bool sendDUPProbe(unsigned long addr)
   217:         {
   218:         struct  in_addr diaddr,siaddr;
   219:         diaddr.s_addr = addr;
   220: 
   221:         if ( send_pack( m_arp_socket, siaddr, diaddr, &m_slladdr, &m_dlladdr ) < 0 ) 
   222:             {
   223:             printf( "Error send packet: %s\n", strerror(errno) );
   224:             return false;
   225:             }
   226:         return true;
   227:         }
   228: 
   229:     /////////////////////////////////////////////////////////////////////////////
   230:     //
   231:     // Try to get an response 
   232:     // return value of 0  = timeout or non duplicate address -> did not find ip
   233:     // return value of 1  = found ip
   234:     // return value of -1 = error
   235:     //
   236:     ///////////////////////////////////////////////////////////////////////////////
   237:     int RecvDUPResp( const unsigned long &addr, unsigned char *mac )
   238:         {
   239:         struct timeval  tv;
   240:         fd_set          rset;
   241:         struct in_addr  siaddr,diaddr;
   242: 
   243:         tv.tv_sec = 0;
   244:         tv.tv_usec = RESP_TIMEOUT;
   245:         FD_ZERO( &rset );
   246:         FD_SET( m_arp_socket, &rset );
   247:         
   248:         int ret = select( m_arp_socket + 1, &rset, NULL, NULL, &tv );
   249:         if ( -1 == ret )        return -1;
   250:         else if ( 0 == ret )    return  0; // Timeout
   251: 
   252:         if ( FD_ISSET( m_arp_socket, &rset ) )
   253:             {
   254:             unsigned char buff[1024];
   255:             struct sockaddr_ll  from;
   256:             unsigned int        alen = sizeof(from);
   257:             
   258:             int len = recvfrom( m_arp_socket, buff, sizeof(buff), 0,(struct sockaddr *)&from, &alen );
   259:             if ( len < 0 ) 
   260:                 {
   261:                 printf( "RecvDUPResp returned an error: %s.\n", strerror(errno) );
   262:                 return -1;
   263:                 }
   264:                 
   265:             if ( recv_pack( buff, len, &from, siaddr, diaddr, mac ) == 1 ) 
   266:                 {
   267:                 if ( addr == siaddr.s_addr )
   268:                     {
   269:                     return 1;
   270:                     }
   271:                 }
   272:             }
   273:         return 0;
   274:         }
   275: 
   276: public:
   277:     ///////////////////////////////////////////////////////////////////////////////
   278:     //
   279:     // Test if ip already exists on the network
   280:     //
   281:     ///////////////////////////////////////////////////////////////////////////////
   282:     bool testIP( const unsigned long & ip, unsigned char mac[6] )
   283:         {
   284:         memset( mac, 0x0, sizeof(mac) );
   285:         
   286:         // Try 3 times to get an answer
   287:         for ( int k = 0; k < MAX_SEND; ++k ) 
   288:             {
   289:             printf( "send probe #%d\n", k+1 ); 
   290:             
   291:             // Send arp request
   292:             if ( !sendDUPProbe( ip ) )
   293:                 {
   294:                 printf("testIP: Error in sendDUPProbe()\n" );
   295:                 exit( 1 );
   296:                 }
   297:                 
   298:             // Try to get Response
   299:             for ( int j = 0; j < MAX_RECV; ++j )
   300:                 {
   301:                 int ret = RecvDUPResp( ip, mac );
   302:                 if ( 1 == ret )
   303:                     {
   304:                     return true;
   305:                     }
   306:                 else if ( -1 == ret )
   307:                     {
   308:                     printf("testIP: Error in RecvDUPResp()\n" );
   309:                     exit( 1 );
   310:                     }
   311:                 }
   312:             }
   313:         return false;
   314:         }
   315: };
   316: 
   317: ///////////////////////////////////////////////////////////////////////////////
   318: //
   319: // Send out an arp request for an given ip address over an given device,
   320: // in order to find out if ip address already exists on network.
   321: // 
   322: // Bugs: on some machines local addresses cannot be resolved.
   323: //
   324: ///////////////////////////////////////////////////////////////////////////////
   325: int main( int argc, char * argv[] )
   326: {
   327:     char * device = "eth0";
   328:     char * progname = argv[0];
   329:     
   330:     if ( argc < 2 )
   331:         {
   332:         printf("1. Usage: %s ip-address [device] ( default: eth0 )\n", progname );
   333:         exit( 1 );
   334:         }
   335:     else if ( 3 == argc )
   336:         {
   337:         device = argv[2];
   338:         printf( "device = %s\n", device );
   339:         }
   340:     else if ( argc > 3 )
   341:         {
   342:         printf("2. Usage: %s ip-address [device] ( default: eth0 )\n", progname );
   343:         exit( 1 );
   344:         }
   345:     
   346:     CArpTest arp( device );
   347:     unsigned char mac[6];   
   348:     unsigned long ip = inet_addr( argv[1] );
   349: 
   350:     if ( arp.testIP( ip, mac ) )
   351:         {
   352:         printf( "The ip address %s already exists on a card with the mac %02X:%02X:%02X:%02X:%02X:%02X.\n", 
   353:                 argv[1], mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   354:         }
   355:     else
   356:         {
   357:         printf( "Ip address %s is not in use.\n", argv[1] );
   358:         }
   359: 
   360: return 0;
   361: }
   362:         
   363: 
   364: