Giriş
getifaddrs() metodu Linux'ta kullanılıyor. Layer 2 ve Layer 3 bilgisini ayrı ayrı veriyor. Örneğin eth0 bu metodla iki defa okunur. İlk okumada Layer 3, ikinci okuma da Layer 2 bilgisi gelir. Her ikisini birbirinden ayırmak içim ifa_addr->family alanı kullanılır. Bu alan Layer 2 için eski ismiyle AF_PACKET yeni ismiyle PF_PACKET değerini alır. Layer 3 içinse AF_INET değerini alır.
Dolayısıyla MAC adresini almak için Layer 2 arayüzler süzülür. İskelet olarak şöyle bir kod yazılır. ifaddrs belleği getifaddrs() çağrısı tarafından yaratılır ve doldurulur. İşimiz bitince bu bellek free() ile temizlenir.
Kodda ifa_addr alanının NULL olmadığı kontrol ediliyor. Sebebi şu.
ifa_addr alanı ve tipi
Açıklaması şöyle
ifa_addr alanı ipv4 ise
Eğer bir arayüzün AF_PACKET yani Layer 2 olduğunu biliyorsak MAC adresini sockaddr_ll'ye cast eder ve şöyle alırız.
ifa_flags alanı
Ağ arayüzünün Layer 2 adresi olsa bile kart çalışmıyor olabilir. Örneğin kablosu çekilmiştir. Bu durumu da algılamak istersek şöyle yapabiliriz.
Arayüzün ismin verir. Şöyle yaparız.
getifaddrs() metodu Linux'ta kullanılıyor. Layer 2 ve Layer 3 bilgisini ayrı ayrı veriyor. Örneğin eth0 bu metodla iki defa okunur. İlk okumada Layer 3, ikinci okuma da Layer 2 bilgisi gelir. Her ikisini birbirinden ayırmak içim ifa_addr->family alanı kullanılır. Bu alan Layer 2 için eski ismiyle AF_PACKET yeni ismiyle PF_PACKET değerini alır. Layer 3 içinse AF_INET değerini alır.
Dolayısıyla MAC adresini almak için Layer 2 arayüzler süzülür. İskelet olarak şöyle bir kod yazılır. ifaddrs belleği getifaddrs() çağrısı tarafından yaratılır ve doldurulur. İşimiz bitince bu bellek free() ile temizlenir.
struct ifaddrs *ifa;
if (getifaddrs(&ifaddr) == -1)
{
perror("getifaddrs");
exit(EXIT_FAILURE);
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
if (ifa->ifa_addr->sa_family==AF_PACKET))
{
...
}
}
freeifaddrs(ifaddr);
ifa_addr alanıKodda ifa_addr alanının NULL olmadığı kontrol ediliyor. Sebebi şu.
The ifa_addr field references either the address of the interface or the link level address of the interface, if one exists, otherwise it is NULL. (The sa_family field of the ifa_addr field should be consulted to determine the format of the ifa_addr address.)Yani süzme için kullandığımız ifa_addr alanı NULL gelebilir ya da bir başka deyişle Layer 2 veya Layer 3 adrese sahipse olmayabilir.
Açıklaması şöyle
The ifa_addr field points to a structure containing the interface address. (The sa_family subfield should be consulted to determine the format of the address structure.) This field may contain a null pointer.Alanın tipi AF_PACKET, AF_INET, AF_INET6 olabilir. Tipin kontrolü için örnek ver
ifa_addr alanı ipv4 ise
Eğer bir arayüzün AF_PACKET yani Layer 2 olduğunu biliyorsak MAC adresini sockaddr_ll'ye cast eder ve şöyle alırız.
struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr;
int i;
int len = 0;
for(i = 0; i < 6; i++)
len+=sprintf(macp+len,"%02X%s",s->sll_addr[i],i < 5 ? ":":"");
Diğer Unix sistemleri de benzer bir mantık kullanıyor. Örneğin BSD'de AF_PACKET yerine AF_LINK arayüzü olması bekleniyor. Arayüz de sockaddr_dl yapısına cast edilip kullanılıyor.ifa_flags alanı
Ağ arayüzünün Layer 2 adresi olsa bile kart çalışmıyor olabilir. Örneğin kablosu çekilmiştir. Bu durumu da algılamak istersek şöyle yapabiliriz.
if (ifa->ifa_flags & IFF_RUNNING) {...} //Arayüzü kullanabiliriz
ifa_name alanıArayüzün ismin verir. Şöyle yaparız.
string interfaceName (ifa->ifa_name);
if(interfaceName == string("lo")) {...}
Hiç yorum yok:
Yorum Gönder