#include #include #include #include #include #include #include #include #include struct arp_packet { u_char targ_hw_addr[6]; u_char src_hw_addr[6]; u_short frame_type; u_short hw_type; u_short prot_type; u_char hw_addr_size; u_char prot_addr_size; u_short op; u_char sndr_hw_addr[6]; u_char sndr_ip_addr[4]; u_char rcpt_hw_addr[6]; u_char rcpt_ip_addr[4]; u_char padding[18]; }; /**************************************************************/ /* conversion de texte en tableau */ void lit_adip(u_char buf[4], char* str) { unsigned long int longint; longint=inet_addr(str); buf[0]=(u_char)(0xff & longint); buf[1]=(u_char)(0xff & (longint>>8)); buf[2]=(u_char)(0xff & (longint>>16)); buf[3]=(u_char)(0xff & (longint>>24)); } void lit_adeth(u_char buf[6], char* str) { int i; char c, val; for(i=0;i<6;i++) { if( !(c = tolower(*str++))) puts("Invalid hardware address"); if(isdigit(c)) val = c-'0'; else if(c >= 'a' && c <= 'f') val = c-'a'+10; else puts("Invalid hardware address"); *buf = val << 4; if( !(c = tolower(*str++))) puts("Invalid hardware address"); if(isdigit(c)) val = c-'0'; else if(c >= 'a' && c <= 'f') val = c-'a'+10; else puts("Invalid hardware address"); *buf++ |= val; if(*str == ':')str++; } } /* affichage d'adresses */ void aff_adip(u_char ip[4]) { printf("%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); } void aff_adeth(u_char eth[6]) { printf("%02X:%02X:%02X:%02X:%02X:%02X\n", eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); } /**************************************************************/ /* fonction de bas niveau */ #define DEFAULT_DEVICE "eth0" void envoie_arp_rarp_brut(u_char eth_src[6], u_char eth_dst[6], u_char src_adeth[6], u_char src_adip[4], u_char dst_adeth[6], u_char dst_adip[4], int type) /*1:arprequest ; 2:arprep ; 3:rarpreq*/ { struct arp_packet pkt; struct sockaddr sa; int sock, type_arp_rarp; if ( type == 1 || type == 2 ) type_arp_rarp=0x0806; /*0x0806:arp*/ else type_arp_rarp=0x8035; /*0x8035:rarp*/ memcpy(pkt.targ_hw_addr, eth_dst, 6); /*entete ethernet: dst*/ memcpy(pkt.src_hw_addr, eth_src, 6); /*entete ethernet: src*/ pkt.frame_type = htons(type_arp_rarp); /*0x0806:arp ; 0x8035:rarp*/ pkt.hw_type = htons(1); /*type Ethernet 10Mps*/ pkt.prot_type = htons(0x0800); /*0x0800:ip*/ pkt.hw_addr_size = 6; pkt.prot_addr_size = 4; pkt.op=htons(type); /*1: arp request ; 2: arp reply ; 3: rarp request*/ memcpy(pkt.sndr_hw_addr, src_adeth, 6); memcpy(pkt.sndr_ip_addr, src_adip, 4); memcpy(pkt.rcpt_hw_addr, dst_adeth, 6); memcpy(pkt.rcpt_ip_addr, dst_adip, 4); bzero(pkt.padding,18); sock=socket(AF_INET, SOCK_PACKET, htons(type_arp_rarp)); if (sock<0){ perror("socket"); exit(1); } strcpy(sa.sa_data, DEFAULT_DEVICE); /*envoie sur l'interface ethi*/ if(sendto(sock, &pkt, sizeof(pkt), 0, &sa, sizeof(sa)) < 0){ perror("sendto"); exit(1); } } void envoie_arp_rarp(u_char src_adeth[6], u_char src_adip[4], u_char dst_adeth[6], u_char dst_adip[4], int type) { envoie_arp_rarp_brut(src_adeth, dst_adeth, src_adeth, src_adip, dst_adeth, dst_adip, type); } /**************************************************************/ /* fonctions d'envoi de requete*/ void envoie_requete_arp(u_char adip[4]) { u_char zero_eth[6], zero_ip[4]; lit_adeth(zero_eth, "00:00:00:00:00:00"); lit_adip(zero_ip, "0.0.0.0"); envoie_arp_rarp(zero_eth, zero_ip, zero_eth, adip, 1); } void envoie_reponse_arp(u_char adeth[6], u_char adip[4]) { u_char zero_eth[6], zero_ip[4]; lit_adeth(zero_eth, "00:00:00:00:00:00"); lit_adip(zero_ip, "0.0.0.0"); envoie_arp_rarp(adeth, adip, zero_eth, zero_ip, 2); } void envoie_requete_rarp(u_char adeth[6]) { u_char zero_eth[6], zero_ip[4]; lit_adeth(zero_eth, "00:00:00:00:00:00"); lit_adip(zero_ip, "0.0.0.0"); envoie_arp_rarp(zero_eth, zero_ip, adeth, zero_ip, 3); } void envoie_reponse_rarp(u_char adeth[6], u_char adip[4]) { u_char zero_eth[6], zero_ip[4]; lit_adeth(zero_eth, "00:00:00:00:00:00"); lit_adip(zero_ip, "0.0.0.0"); envoie_arp_rarp(zero_eth, zero_ip, adeth, adip, 4); } /**************************************************************/ /* demande au système des entrées dans la table arp ou rarp*/ int arp(char *ip, char *ether) { int sfd, retour; struct arpreq ar; struct sockaddr_in *sin; /* on affecte la partie IP */ bzero((char *)&ar, sizeof(ar)); sin = (struct sockaddr_in *)&ar.arp_pa; sin->sin_family = AF_INET; bcopy(ip, (char *)&sin->sin_addr.s_addr, 4); /* on fait la requete */ sfd = socket(AF_INET, SOCK_DGRAM, 0); if ( sfd == -1) return 1; retour = ioctl(sfd, SIOCGARP, (caddr_t)&ar); if ( retour == -1) return 2; bcopy(ar.arp_ha.sa_data, ether, 6); return 0; } int rarp(char *ether, char *ip) { int sfd, retour; struct arpreq ar; struct sockaddr_in *sin; /* on affecte la partie ethernet */ bzero((char *)&ar, sizeof(ar)); sin = (struct sockaddr_in *)&ar.arp_pa; ar.arp_pa.sa_family = AF_INET; bcopy(ip, (char *)&sin->sin_addr.s_addr, 4); bcopy(ether, ar.arp_ha.sa_data, 6); /* on fait la requete */ sfd = socket(AF_INET, SOCK_DGRAM, 0); if ( sfd == -1) return 1; retour = ioctl(sfd, SIOCGRARP, (caddr_t)&ar); if ( retour == -1) return 2; bcopy(ar.arp_ha.sa_data, ether, 6); bcopy((char *)&sin->sin_addr.s_addr, ip, 4); return 0; } /**************************************************************/ /**************************************************************/ int main(int argc, char** argv) { u_char eth[6], ip[4]; int retour; /*demande qui a 192.168.10.52*/ lit_adip(ip, "192.168.10.52"); envoie_requete_arp(ip); /*dit que 192.168.10.152 a pour adresse 1:2:3:4:5:6*/ lit_adip(ip, "192.168.10.152"); lit_adeth(eth, "01:02:03:04:05:06"); envoie_reponse_arp(eth, ip); /*demande qui a 4:5:6:7:8:9*/ lit_adeth(eth, "04:05:06:07:08:09"); envoie_requete_rarp(eth); /*dit que 11:22:33:44:55:66 a pour adresse 192.168.10.111*/ lit_adip(ip, "192.168.10.111"); lit_adeth(eth, "11:22:33:44:55:66"); envoie_reponse_rarp(eth, ip); /*interroge le système*/ /*ARP (commande arp -a)*/ lit_adeth(eth, "00:00:00:00:00:00"); lit_adip(ip, "192.168.10.1"); retour=arp(ip, eth); printf(" %d(%d) : ", retour, errno); aff_adeth(eth); lit_adip(ip, "192.168.10.3"); retour=arp(ip, eth); printf(" %d(%d) : ", retour, errno); aff_adeth(eth); /*RARP (commande rarp -a)*/ lit_adeth(eth, "00:00:00:00:00:00"); lit_adip(ip, "192.168.10.30"); retour=rarp(eth, ip); printf(" %d(%d) : ", retour, errno); aff_adip(ip); aff_adeth(eth); lit_adip(ip, "192.168.10.3"); retour=rarp(eth, ip); printf(" %d(%d) : ", retour, errno); aff_adip(ip); aff_adeth(eth); }