Giriş
Linux üzerinde yaratılan TAP arayüzünden pcap ile okuma işlemi çalışıyor ancak yazma işlemi bir türlü olmadı. Sebebini bilmiyorum.
Windows üzerinde yaratılan TAP arayüzünden pcap ile okuma ve yazma işlemi sorunsuz çalışıyor.
Linux Komut Satırı
Sanal bir arayüz oluşturmak için
kullanılabilir.
1. Önce arayüz
oluşturulur
ip tuntap add mode tap myintf
veya şöyle
yaparız. Ben bunu kullandım.
ip tuntap add dev myintf mode tap
2. Arayüzü ayağa kaldırırız.
ifconfig myintf up
veya şöyle yaparız. Ben bunu kullandım
ip link set myintf up
3. IP adresi
atarız.
ip a a 192.168.1.1/24 dev myintf
Ben bunu kullandım
ip addr 10.0.0.1/24 dev myintf
IP adresi ve broadcast adresi atamak istersek şöyle
yaparız.
ip addr add dev tap0 10.7.110.110/16 broadcast 10.7.255.255
Oluşan arayüz geçicidir. Kalıcı olması için /etc/network/interfaces dosyasına yazılması gerekir.
Ayrıca arayüz UP, BROADCAST olarak görünür ama RUNNING değildir. Bir yazılım ilk defa bu arayüze bağlanınca RUNNING olur. Yani ethernet kartına kablonun takılması gibi düşünülebilir.
Linux API
1. Yaratma
Hataları ele almayı gözardı edersek device şöyle
yaratılır veya etkinleştirilir. Eğer tap arayüzü varsa ağ arayüzü etkinleşir. Yani arayüz RUNNING olur. Yoksa arayüz yaratılır. IFF_NO_PI bayrağı ile sadece ethernet paketlerini yakalarız. TAP bize fazladan byte'lar vermez.
char *dev = "myintf"
struct ifreq ifr;
char *clonedev = "/dev/net/tun";
//open the clone device
int fd = open(clonedev, O_RDWR);
//preparation of the struct ifr, of type "struct ifreq"
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, dev, IFNAMSIZ);
//try to create the device
ioctl(fd, TUNSETIFF, (void *) &ifr);
2. MAC Adresi Verme
struct ifreq ifr;
ifr.ifr_hwaddr.sa_family = 1;
ifr.ifr_hwaddr.sa_data [0] = ...;
ioctl ( fd,SIOCSIFHWADDR,&ifr);
3.IP Adresi Verme
Sıfırdan yaratılan tap arayüzü henüz bir IP, Netmask ve Broadcast adresine sahip değildir. Eğer bu değerleri komut satırından atamadıysak kod ile atamamız gerekir.
Şu satırı dahil
ederiz.
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
Şöyle
yaparız.
struct ifreq ifr;
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
const char * name = "eth0";
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_addr.sa_family = AF_INET;
inet_pton(AF_INET, "10.10.2.59", &addr->sin_addr);
if(ioctl(fd, SIOCSIFADDR, &ifr) < 0)
{
std::cout << "Failed to set IP: " << strerror(errno) << std::endl;
return -1;
}
close (fd);
Netmask vermek için yine aynı şekilde adres alanı doldurulur.
ioctl (sock,SIOCSIFNETMASK,&ifr);
Broadcast adresi vermek için
ioctl(sock,SIOCSIFBRDADDR);
yapılır.
4. UP Yapma
Şöyle
yaparız.
struct ifreq ifr;
const char * name = "eth0";
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
strncpy(ifr.ifr_name, name, IFNAMSIZ);
if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
std::cout << "Failed to get flags: " << strerror(errno) << std::endl;
return -2;
}
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
{
std::cout << "Failed to set flags: " << strerror(errno) << std::endl;
return -3;
}alo
close (fd);
5.Okuma
Tap arayüzünden okuma için şöyle
yaparız. Eğer arzu edilirse select () çağrısı da kullanılabilir.
char buffer[1600];
read(fd, buffer, sizeof(buffer));
6 Yazma
write (...) çağrısı kullanılır.
7. Kapatma
Tap arayüzünü kapatmak için şöyle
yaparız. Kodla yaratılan ağ arüyüzü geçici olduğu için uygulama sonlanınca arayüz de yok edilir. Yani aslında kapatmasak ta olur ama ben kapatmayı tercih ediyorum.
close(fd);
Windows
Windows'ta TUN/TAP sürücüsü kurmak için OpenVPN kurulumunu yaparken diğer tüm seçenekleri kaldırıp sadece TAP seçeneğini kurmak gerekiyor. Kurulan TAP sürücüsünün "Media Sensing" ayarı etkin geliyor ve üzerinde çarpı işareti var. Bu ayarı devre dışı bırakmak için şöyle
yaparız.
1. Go into device manager
2. Find your Tap Adapter
3. Right click
4. Select "Propterties"
5. Select "Advanced Media Status"
6. Set it to "Always Connected"
7. Click Ok
8. Restart computer.