宏定义中的HOST_NAME是网卡设备名
scan.h
#ifndef __SCAN__H_
#define __SCAN__H_
#include <stdio.h>
#include <sys/time.h>
#include <netdb.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/ip_icmp.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <pthread.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <sys/ioctl.h>
#define IP_LEN 4
#define MAC_LEN 6
#define ON 1
#define OFF 0
#define ETH_HEAD_LEN 14
#define ARP_LEN 28
#define BUFF_LEN (ETH_HEAD_LEN+ARP_LEN+18)
#define TOTAL_HOST_NUM 256
#define HOST_NAME "ens33"
#define SEND_LEN 64
#define WAIT_TIME 50000
#define ARP_TYPE 0x0806
struct host {
unsigned char IP[IP_LEN];
unsigned char MAC[MAC_LEN];
int is_on;
struct host *next;
};
struct eth_head {
unsigned char des_mac[6];
unsigned char src_mac[6];
unsigned short type;
};
struct arp_msg {
unsigned short hdware_type;
unsigned short protocol;
unsigned char mac_len;
unsigned char ip_len;
unsigned short op_type;
unsigned char src_mac[6];
unsigned char src_ip[4];
unsigned char des_mac[6];
unsigned char des_ip[4];
};
struct host* host_init();
struct host* host_insert(struct host *head,char *IP,char *MAC);
int host_select(struct host *head,char *IP);
int host_update(struct host *head,char *IP,int stat);
struct host* scan(struct host* head);
int show_online(struct host* head);
int set_eth_head(struct eth_head *eth,char *des_mac);
int set_arp_msg(struct arp_msg* arp,char *des_ip,char *des_mac);
int initialize_sockaddr_ll(struct sockaddr_ll *sock_addr , struct ifreq *ifr ,int ifindex);
int get_local_mac(unsigned char *mac);
int get_local_ip(unsigned char *ip);
int show_online_host(struct host *head);
int free_host(struct host *head);
#endif
scan.c
#include "scan.h"
struct host * host_init()
{
unsigned char mac[MAC_LEN+1] = {0};
unsigned char ip[IP_LEN+1] = {0};
struct host *head = (struct host *)malloc(sizeof(struct host));
if(-1 == get_local_mac(mac))
{
printf("%s\n",__func__);
return NULL;
}
if(-1 == get_local_ip(ip))
{
printf("%s\n",__func__);
return NULL;
}
strncpy(head->IP,ip,IP_LEN);
memmove(head->MAC,mac,MAC_LEN);
head->next = NULL;
head->is_on = ON;
return head;
}
int get_local_mac(unsigned char *mac)
{
if(NULL == mac){
printf("%s\n",__func__);
return -1;
}
struct ifreq ifr;
bzero(&ifr,sizeof(struct ifreq));
strncpy(ifr.ifr_name, "ens33", sizeof(ifr.ifr_name) - 1);
int sd = socket(AF_INET,SOCK_STREAM,0);
if(0>sd){
printf("%s\n",__func__);
return -1;
}
int ret = ioctl(sd, SIOCGIFHWADDR, &ifr);
if(0>ret){
printf("%s\n",__func__);
close(sd);
return -1;
}
for(int i=0;i<MAC_LEN;i++){
mac[i]=(unsigned char)ifr.ifr_hwaddr.sa_data[i];
}
//printf("%p\n",mac);
close(sd);
}
int get_local_ip(unsigned char *ip)
{
if(NULL == ip){
printf("%s\n",__func__);
return -1;
}
struct ifreq ifr;
bzero(&ifr,sizeof(struct ifreq));
strncpy(ifr.ifr_name, "ens33", sizeof(ifr.ifr_name) - 1);
int sd = socket(AF_INET,SOCK_STREAM,0);
if(0>sd){
printf("%s\n",__func__);
return -1;
}
int ret = ioctl(sd, SIOCGIFADDR, &ifr);
if(0>ret){
perror("ioctl IP");
close(sd);
return -1;
}
struct sockaddr_in sin;
memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
memmove(ip,&sin.sin_addr, IP_LEN);
return 0;
}
struct host* host_insert(struct host *head,char *IP,char *MAC)
{
if(NULL == head){
printf("insert head\n");
return NULL;
}
if(NULL == IP){
printf("insert IP\n");
return NULL;
}
if(NULL == MAC){
printf("insert MAC\n");
return NULL;
}
struct host *ptr = (struct host *)malloc(sizeof(struct host));
memmove(ptr->IP,IP,IP_LEN);
memmove(ptr->MAC,MAC,MAC_LEN);
ptr->is_on = 1;
ptr->next = head;
head = ptr;
return head;
}
int host_select(struct host *head,char *IP)
{
struct host *ptr = head;
while (ptr)
{
if(0 == strncmp(ptr->IP,IP,IP_LEN)){
break;
}
ptr = ptr->next;
}
if(ptr){
return 1;
}else{
return 0;
}
}
int host_update(struct host *head,char *IP,int stat)
{
struct host *ptr = head;
while (ptr)
{
if(0 == strncmp(ptr->IP,IP,IP_LEN)){
break;
}
ptr = ptr->next;
}
if(ptr){
ptr->is_on = stat;
}else{
printf("no such IP!!\n");
return -1;
}
return 0;
}
struct host * scan(struct host* head)
{
if(NULL!=head->next){
printf("head node is not local");
return NULL;
}
printf("scanning.....\n");
struct ifreq ifr; //用于存放网卡的相关信息
struct sockaddr_ll sock_addr;
int addrlen = sizeof(sock_addr);
unsigned char ip[IP_LEN+1] = {0};
unsigned char mac[MAC_LEN+1] = {0};
char send_buffer[BUFF_LEN+1] = {0};
char recv_buffer[BUFF_LEN+1] = {0};
struct eth_head *ethhead = (struct eth_head *)send_buffer;
struct arp_msg *arpmsg = (struct arp_msg *)(send_buffer + ETH_HEAD_LEN);
strncpy(ip,head->IP,IP_LEN);
unsigned long ul = 1;
int ret = 0;
int sock_scan=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ARP));
if(0 > sock_scan){
perror("socket");
return NULL;
}
//设置为非阻塞接收
ret = ioctl(sock_scan,FIONBIO,(unsigned long*)&ul);
if(0 > ret){
perror("ioctlsocket");
close(sock_scan);
return NULL;
}
//网卡信息
strncpy(ifr.ifr_name,HOST_NAME,sizeof(ifr.ifr_name)-1);
if(ioctl(sock_scan,SIOCGIFINDEX,&ifr)==-1)
{
perror("SIOCGIFINDEX");
close(sock_scan);
return NULL;
}
int ifindex = ifr.ifr_ifindex;
if(ioctl(sock_scan,SIOCGIFHWADDR,&ifr)==-1) //通过ioctl获取网卡MAC地址存放到ifr结构体中
{
perror("SIOCGIFHWADDR");
close(sock_scan);
return NULL;
}
//设置sockaddr_ll
if(initialize_sockaddr_ll(&sock_addr , &ifr ,ifindex) == -1)
{
printf("sockaddr_ll error\n");
close(sock_scan);
return NULL;
}
for (int i = 0; i < TOTAL_HOST_NUM; i++)
{
ip[3] = i;
if(-1 == set_eth_head(ethhead,NULL)){
printf("set eth head error!!\n");
close(sock_scan);
return NULL;
}
if(-1 == set_arp_msg(arpmsg,ip,NULL)){
printf("set_arp_msg error!!\n");
close(sock_scan);
return NULL;
}
if(sendto(sock_scan,send_buffer,SEND_LEN,0,(struct sockaddr*)&sock_addr,sizeof(sock_addr))==-1)
{
perror("sendtos");
close(sock_scan);
return NULL;
}
usleep(WAIT_TIME);
ret = recvfrom(sock_scan,recv_buffer,BUFF_LEN,0,(struct sockaddr*)&sock_addr,&addrlen);
if(0 == ret)
continue;
else if(ret>0){
memmove(mac,&recv_buffer[6],MAC_LEN);
if((unsigned char)recv_buffer[31] == (unsigned char)i){
if(NULL == (head = host_insert(head,ip,mac))){
close(sock_scan);
return NULL;
}
}
}
bzero(send_buffer,sizeof(send_buffer));
bzero(recv_buffer,sizeof(recv_buffer));
}
return head;
}
int set_eth_head(struct eth_head *eth,char *des_mac)
{
if(NULL == eth){
printf("eth_head point to NULL!!\n");
return -1;
}
unsigned char local_mac[MAC_LEN+1] = {0};
if(NULL == des_mac){
for(int i=0;i<MAC_LEN;i++){
eth->des_mac[i] = (unsigned char)0xff;
}
}else{
strncpy(eth->des_mac,des_mac,MAC_LEN);
}
if(-1 == get_local_mac(local_mac)){
return -1;
}
//printf("%p\n",local_mac);
memmove(eth->src_mac,local_mac,MAC_LEN);
//printf("%02x:%02x:%02x:%02x:%02x:%02x\n",eth->src_mac[0],eth->src_mac[1],eth->src_mac[2],eth->src_mac[3],eth->src_mac[4],eth->src_mac[5]);
eth->type = htons(ARP_TYPE);
}
int set_arp_msg(struct arp_msg* arp,char *des_ip,char *des_mac)
{
if(NULL == arp||NULL == des_ip)
{
printf("%s\n",__func__);
return -1;
}
if(NULL == des_mac){
for (int i = 0; i < MAC_LEN; i++){
arp->des_mac[i] = 0;
}
}else{
strncpy(arp->des_mac,des_mac,MAC_LEN);
}
arp->hdware_type = htons(0x01);
arp->protocol = htons(0x0800);
arp->mac_len = 6;
arp->ip_len = 4;
arp->op_type = htons(1);
unsigned char send_mac[MAC_LEN+1] = {0};
if(-1 == get_local_ip(arp->src_ip)){
printf("%s\n",__func__);
return -1;
}
if(-1 == get_local_mac(send_mac)){
printf("%s\n",__func__);
return -1;
}
strncpy(arp->des_ip,des_ip,IP_LEN);
memmove(arp->src_mac,send_mac,MAC_LEN);
return 0;
}
int initialize_sockaddr_ll(struct sockaddr_ll *sock_addr , struct ifreq *ifr ,int ifindex)
{
if(sock_addr == NULL || ifr ==NULL)
{
printf("sockaddr_ll or ifreq is a null pointer\n");
return -1;
}
int i =0;
//设置sockaddr_ll结构体的信息
for(i=0;i<MAC_LEN;i++)
{
sock_addr->sll_addr[i]=(unsigned char)ifr->ifr_hwaddr.sa_data[i];
}
sock_addr->sll_family = PF_PACKET;
sock_addr->sll_protocol = htons(ETH_P_ARP); //协议类型
sock_addr->sll_ifindex =ifindex; //网卡序列号
//printf("%d,%d\n",ifindex,ifr->ifr_ifindex);
sock_addr->sll_hatype = htons(ARPHRD_ETHER); //ARP硬件地址类型
sock_addr->sll_halen = ETH_ALEN; //硬件地址长度
return 0;
}
int show_online_host(struct host *head)
{
struct host *node = head;
while(node){
if(node->is_on){
printf("IP:");
for(int i=0;i<IP_LEN;i++){
if(i == IP_LEN-1){
printf("%d",node->IP[i]);
}else{
printf("%d.",node->IP[i]);
}
}
printf("-------MAC");
for(int i=0;i<MAC_LEN;i++){
printf(":%02x",node->MAC[i]);
}
printf("---------on\n");
}
node = node->next;
}
return -1;
}
int free_host(struct host *head)
{
if(NULL == head){
printf("head point to NULL!!\n");
return -1;
}
struct host *ptr;
ptr = head->next;
while (ptr)
{
free(head);
head = ptr;
ptr = ptr->next;
}
free(head);
return 0;
}
main.c
#include "scan.h"
struct host *head = NULL;
int main()
{
struct host *head;
head = host_init(head);
head = scan(head);
show_online_host(head);
free_host(head);
return 0;
}