Giriş
PF_PACKET (eski kodlarda AF_PACKET olarak geçer) socketi Linux'a mahsustur. Ethernet seviyesindeki paketler alıp gönderebilmemizi sağlar.
1. Parametre
PF_PACKET yerine eski kodlarda SOCK_PACKET sabiti de görülebilir.
2. Parametre
SOCK_DGRAM veya SOCK_RAW olabilir. SOCK_DGRAM ise paketi gönderirken ethernet header bizim için doldurulur. SOCK_RAW ise ethernet header'ını doldurmamız gerekir. Aslınad bu kısmı hiç SOCK_DGRAM olarak kullanmadım. Bu yüzden emin değilim.
3. Parametre
Hangi tip ethernet paketlerini almak istediğimizi belirtiriz. Ethernet frame type ta diyebiliriz. Bu alan Big Endian formatındadır. 2 byte uzunluğundadır ve genellikle 0x800'den başlar.
IP paketleri için Wireshark şunu gösterir.
Type: IP (0x0800)
Örnek
Şöyle yaparız
ETH_P_IP ile IPv4 paketleri alınır.
ETH_P_IPV6, ETH_P_ARP gibi IPv6 ve ARP paketlerini alma seçenekleri de var.
Örnek
Şöyle yaparız.
bind metodu
Eğer sadece belli bir arayüzden paket yakalamak istersek socketi bind etmek gerekir. sockaddr_ll veriyapısı doldurulur ve bind metodu çağrılır. sockaddr_ll içine family olarak PF_PACKET ifindex olarak ise bind edilmek istenen arayüzün numarası atanır. Arayüzün numarası eğer bilinmiyorsa ismi kullanılarak ioctl + SIOCGIFINDEX ile bulunabilir.
Örnek
Şöyle yaparız.
Şöyle yaparız.
Ethernet kartları kendi MAC adreslerine gönderilmemiş paketleri içeri almazlar. Yukarıdaki seçeneklerin çalışması için ethernet kartının promiscuous moda sokulması gerekir. Bunun için yeni kodlarda PACKET_ADD_MEMBERSHIP kullanılır.Örnek
Şöyle yaparız.
PF_PACKET (eski kodlarda AF_PACKET olarak geçer) socketi Linux'a mahsustur. Ethernet seviyesindeki paketler alıp gönderebilmemizi sağlar.
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)
socket metodu1. Parametre
PF_PACKET yerine eski kodlarda SOCK_PACKET sabiti de görülebilir.
2. Parametre
SOCK_DGRAM veya SOCK_RAW olabilir. SOCK_DGRAM ise paketi gönderirken ethernet header bizim için doldurulur. SOCK_RAW ise ethernet header'ını doldurmamız gerekir. Aslınad bu kısmı hiç SOCK_DGRAM olarak kullanmadım. Bu yüzden emin değilim.
3. Parametre
Hangi tip ethernet paketlerini almak istediğimizi belirtiriz. Ethernet frame type ta diyebiliriz. Bu alan Big Endian formatındadır. 2 byte uzunluğundadır ve genellikle 0x800'den başlar.
IP paketleri için Wireshark şunu gösterir.
Type: IP (0x0800)
Örnek
Şöyle yaparız
ETH_P_ALL ile tüm ethernet paketleri alınır.fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //Tüm paketler
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); //Incoming IP paketleri
ETH_P_IP ile IPv4 paketleri alınır.
ETH_P_IPV6, ETH_P_ARP gibi IPv6 ve ARP paketlerini alma seçenekleri de var.
Örnek
Şöyle yaparız.
if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) == -1) {
perror("socket");
exit(1);
}
bind metodu
Eğer sadece belli bir arayüzden paket yakalamak istersek socketi bind etmek gerekir. sockaddr_ll veriyapısı doldurulur ve bind metodu çağrılır. sockaddr_ll içine family olarak PF_PACKET ifindex olarak ise bind edilmek istenen arayüzün numarası atanır. Arayüzün numarası eğer bilinmiyorsa ismi kullanılarak ioctl + SIOCGIFINDEX ile bulunabilir.
Örnek
Şöyle yaparız.
void BindToInterface(int raw , char *device , int protocol) {
struct sockaddr_ll sll;
struct ifreq ifr;
bzero(&sll , sizeof(sll));
bzero(&ifr , sizeof(ifr));
strncpy((char *)ifr.ifr_name ,device , IFNAMSIZ);
//copy device name to ifr
if((ioctl(raw , SIOCGIFINDEX , &ifr)) == -1)
{
perror("Unable to find interface index");
exit(-1);
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(protocol);
if((bind(raw , (struct sockaddr *)&sll , sizeof(sll))) ==-1)
{
perror("bind: ");
exit(-1);
}
return 0;
}
ÖrnekŞöyle yaparız.
sockaddr_ll sll;
memset(&sll, 0, sizeof(sockaddr));
sockaddr.sll_family = PF_PACKET;
sockaddr.sll_protocol = htons(d_ethtype)
sockaddr.sll_ifindex = if_nametoindex(d_receive_iface.c_str());
sockaddr.sll_hatype = 1;
Promiscuous ModeEthernet kartları kendi MAC adreslerine gönderilmemiş paketleri içeri almazlar. Yukarıdaki seçeneklerin çalışması için ethernet kartının promiscuous moda sokulması gerekir. Bunun için yeni kodlarda PACKET_ADD_MEMBERSHIP kullanılır.Örnek
Şöyle yaparız.
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = interface_index;
mr.mr_type = PACKET_MR_PROMISC;
setsockopt(socFd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr);
struct ifreq ifr;
memset(&ifr, 0, sizeof (struct ifreq));
//Interface adını ver
strncpy(ifr.ifr_name, device, strlen(device) + 1);
//MEvcut flag değerlerini al
ioctl(m_sockfd, SIOCGIFFLAGS, &ifr);
//Yeni değerleri ata
ifr.ifr_flags |= IFF_PROMISC;
ioctl(m_sockfd, SIOCSIFFLAGS, &ifr);
Hiç yorum yok:
Yorum Gönder