Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/udhcp/arpping.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/udhcp/arpping.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 3 * arpping.c … … 6 7 */ 7 8 8 #include <time.h>9 #include <sys/socket.h>10 9 #include <netinet/if_ether.h> 11 10 #include <net/if_arp.h> 12 #include <netinet/in.h>13 #include <string.h>14 #include <unistd.h>15 #include <errno.h>16 11 12 #include "common.h" 17 13 #include "dhcpd.h" 18 #include "arpping.h"19 #include "common.h"20 21 /* args: yiaddr - what IP to ping22 * ip - our ip23 * mac - our arp address24 * interface - interface to use25 * retn: 1 addr free26 * 0 addr used27 * -1 error28 */29 30 /* FIXME: match response against chaddr */31 int arpping(uint32_t yiaddr, uint32_t ip, uint8_t *mac, char *interface)32 {33 34 int timeout = 2;35 int optval = 1;36 int s; /* socket */37 int rv = 1; /* return value */38 struct sockaddr addr; /* for interface name */39 struct arpMsg arp;40 fd_set fdset;41 struct timeval tm;42 time_t prevTime;43 14 44 15 45 if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP))) == -1) { 46 #ifdef IN_BUSYBOX 47 LOG(LOG_ERR, bb_msg_can_not_create_raw_socket); 48 #else 49 LOG(LOG_ERR, "Could not open raw socket"); 50 #endif 16 struct arpMsg { 17 /* Ethernet header */ 18 uint8_t h_dest[6]; /* 00 destination ether addr */ 19 uint8_t h_source[6]; /* 06 source ether addr */ 20 uint16_t h_proto; /* 0c packet type ID field */ 21 22 /* ARP packet */ 23 uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */ 24 uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */ 25 uint8_t hlen; /* 12 hardware address length (must be 6) */ 26 uint8_t plen; /* 13 protocol address length (must be 4) */ 27 uint16_t operation; /* 14 ARP opcode */ 28 uint8_t sHaddr[6]; /* 16 sender's hardware address */ 29 uint8_t sInaddr[4]; /* 1c sender's IP address */ 30 uint8_t tHaddr[6]; /* 20 target's hardware address */ 31 uint8_t tInaddr[4]; /* 26 target's IP address */ 32 uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */ 33 } ATTRIBUTE_PACKED; 34 35 36 /* Returns 1 if no reply received */ 37 38 int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface) 39 { 40 int timeout = 2; 41 int s; /* socket */ 42 int rv = 1; /* "no reply received" yet */ 43 struct sockaddr addr; /* for interface name */ 44 struct arpMsg arp; 45 fd_set fdset; 46 struct timeval tm; 47 unsigned prevTime; 48 49 s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); 50 if (s == -1) { 51 bb_perror_msg(bb_msg_can_not_create_raw_socket); 51 52 return -1; 52 53 } 53 54 54 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) { 55 LOG(LOG_ERR, "Could not setsocketopt on raw socket"); 56 close(s); 57 return -1; 55 if (setsockopt_broadcast(s) == -1) { 56 bb_perror_msg("cannot setsocketopt on raw socket"); 57 goto ret; 58 58 } 59 59 60 60 /* send arp request */ 61 61 memset(&arp, 0, sizeof(arp)); 62 memcpy(arp.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */ 63 memcpy(arp.h_source, mac, 6); /* MAC SA */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 67 arp.hlen = 6; /* hardware address length */ 68 arp.plen = 4; /* protocol address length */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 70 memcpy(arp.sInaddr, &ip, sizeof(ip)); /* source IP address */ 71 memcpy(arp.sHaddr, mac, 6); /* source hardware address */ 72 memcpy(arp.tInaddr, &yiaddr, sizeof(yiaddr)); /* target IP address */ 62 memset(arp.h_dest, 0xff, 6); /* MAC DA */ 63 memcpy(arp.h_source, from_mac, 6); /* MAC SA */ 64 arp.h_proto = htons(ETH_P_ARP); /* protocol type (Ethernet) */ 65 arp.htype = htons(ARPHRD_ETHER); /* hardware type */ 66 arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ 67 arp.hlen = 6; /* hardware address length */ 68 arp.plen = 4; /* protocol address length */ 69 arp.operation = htons(ARPOP_REQUEST); /* ARP op code */ 70 memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */ 71 memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */ 72 /* tHaddr */ /* target hardware address */ 73 memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */ 73 74 74 75 memset(&addr, 0, sizeof(addr)); 75 s trcpy(addr.sa_data, interface);76 safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data)); 76 77 if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) 77 rv = 0;78 goto ret; 78 79 79 /* wait arp reply, and check it */80 tm.tv_usec = 0;81 prevTime = uptime();82 while (timeout > 0) {80 /* wait for arp reply, and check it */ 81 do { 82 int r; 83 prevTime = monotonic_sec(); 83 84 FD_ZERO(&fdset); 84 85 FD_SET(s, &fdset); 85 86 tm.tv_sec = timeout; 86 if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) { 87 DEBUG(LOG_ERR, "Error on ARPING request: %m"); 88 if (errno != EINTR) rv = 0; 89 } else if (FD_ISSET(s, &fdset)) { 90 if (recv(s, &arp, sizeof(arp), 0) < 0 ) rv = 0; 91 if (arp.operation == htons(ARPOP_REPLY) && 92 memcmp(arp.tHaddr, mac, 6) == 0 && 93 *((uint32_t *) arp.sInaddr) == yiaddr) { 94 DEBUG(LOG_INFO, "Valid arp reply receved for this address"); 87 tm.tv_usec = 0; 88 r = select(s + 1, &fdset, NULL, NULL, &tm); 89 if (r < 0) { 90 bb_perror_msg("error on ARPING request"); 91 if (errno != EINTR) 92 break; 93 } else if (r) { 94 if (recv(s, &arp, sizeof(arp), 0) < 0) 95 break; 96 if (arp.operation == htons(ARPOP_REPLY) 97 && memcmp(arp.tHaddr, from_mac, 6) == 0 98 && *((uint32_t *) arp.sInaddr) == test_ip 99 ) { 95 100 rv = 0; 96 101 break; 97 102 } 98 103 } 99 timeout -= uptime() - prevTime; 100 prevTime = uptime(); 101 } 104 timeout -= monotonic_sec() - prevTime; 105 } while (timeout > 0); 106 107 ret: 102 108 close(s); 103 DEBUG( LOG_INFO, "%salid arp replies for this address", rv ? "No v" : "V");109 DEBUG("%srp reply received for this address", rv ? "No a" : "A"); 104 110 return rv; 105 111 }
Note:
See TracChangeset
for help on using the changeset viewer.