Windows Debugging 212

Windows bir ag isletim sistemi olarak tasarlanmistir. Bununla beraber kendi getirdigi ve uyum sagladigi network teknolojileri mevcuttur. Ag yapisi belli standartlar ile olusturulmaktadir. Örnegin TCP/IP 40 sene önce gelistirilmistir. Isletim sisteminin yeri de bu standartlar çerçevesinde bilgisayarlar arasi ag teknolojisi üzerinden haberlesmeyi açik bir sekilde saglamaktir. Yani Windows platformunu kullanarak kendi yazilimlarimizi istedigimiz sekilde çalistirabilmektir.
Burada her seyden evvel Windows da 1980 li yillarda tanimlanis olan OSI referans modeline uyum saglar. Elbette verimlilik ve baska uyumluluk bakis açilarindan dolayi Windows un bunu kendisi uygularken her yedi katman için de 1:1 tasarimsal komponentler yaratilmamistir. Yani disa dönük uyum saglansa da, kendi uyarlamasinda tasarimin modüllerin sorumluluklari katman disina da çikmaktadirlar.

OSI in uyarlandigi Windows komponentlerine baktigimizda ilk önce Network API lere ihtiyacimiz vardir. Bunlar ile network ile ilgili kodumuzu gelistirebiliriz. Buna örnegin Winsock, RPC, Named Pipes ve NetBIOS gibi teknolojilerin API leri dahildir.

Winsock un en büyük farki asenkron IO ya izin vermesidir. Ayni sekilde quality of service QoS u da mümkün kilar. Winsock Extensionlari ile client ve server tarafina göre yazilimsal haberlesme uyarlanabilir. Kisaca çok basit sekilde iki makinedeki yazilimlarimiz arasinda network baglantisini kurduktan sonra, yazilimlar lokalde çalisirmis gibi çok hizli haberlesebilir. Winsock/WSK ile ilgili asagida da aydinlatici bilgiler bulabilirsiniz.

RPC de transport bakis açimiz ön planda degildir. Genelde IRP ile IO yapmak isteriz ve network üzerinden de IO yaptigimizda client tarafinda redirector ile file sistemin uzakta oldugunu aslinda gizleriz. RPC de odak daha çok çalistirilan kodun network de farkli makineler üzerinde çalissa da, sanki bir makinede çalisiyormus kadar kolay bir hale getirebilmektir. Yani RPC altyapisini kullanarak yazilimin farkli makinelerde netwörksel detaylarla çok önem vermeden çalisabilmesini saglamaktir.
Aslinda procedural bir yaklasim, sadece neyin nerede çalisacagina yazilimin alt katmaninda belirlememiz gerekir ve bu da temel kolayligidir. Siz prosedürlerinizi hangi makinede olurlarsa olsunlar, kod akisinda tek makinadaymis gibi normal olusturursunuz. Her farkli sunucuda çalisacak kod için de bir stub imiz olur. Yani kisaca o prosedürü netwörkte nerede bulabilecegimizi RPC runtime altyapisina aktararmamiz yeterli olur. Bu stub lari da örnegin bir DLL de toplayabiliriz.

Burada COM objelerin, netwörk için DCOM objelerin kullanilmasi da çok yaygindir. Tabi altinda yine RPC çalisir, ama DCOM ile yazilimin kendisini kolaylastirmis oluruz.

Named Pipes ve Mailslot lar da örnegin protokol bagimsiz çalisirlar. UNC kullanirlar ve bunlarin API lerini kullanarak farkli sunuculardaki processler arasi iletisim saglariz. Named Pipe ile çift yönlü garantili haberlesme saglanabilir ve daha basit mailslot mantigi ile tek yönlü ve böylece transmission garantisi olmadan haberlesme saglanabilir.

Yani OSI yi uyarlarken, farkli makineler arasinda farkli kodlarin çalismasini ve bunlarin haberlesmesini ve veri aktarabilmesini network API leri kullanarak saglayabiliriz. Burada OSI in üst seviyelerinde oluruz ve örnegin protokol bagimsiz çalisiriz. Ama asagiya indikçe protokolün önemi de artar.

Protokollü çalisan OSI komponentleri saglayabilmek için, protokollerimizi tasiyabilecek, kullanilan API lerin kernel mode tarafindaki tasiyicisi olarak görebilecegimiz transport driver interface, TDI a ihtiyacimiz vardir.
Örnegin baska makineye bir IRP gönderdigimizde, bunu bir protokol sürücüsüne aktaririz ve iste bu sürücü TDI standardina uygundur. (Örnegin tcpip.sys bir protokol sürücüsüdür.)

Bu sürücülere TDI transports diyebiliriz, ve burada network driver interface specification, NDIS protokol sürücüsüne de ihtiyacimiz vardir.
Bu ndis.sys, NDIS library sidir. Yani kernelde yer alan bir fonksiyon kütüphanesidir.
Makineler arasi örnek IRP ümüzü tasirken, iki tarafta da bununla ilgili islemleri yapabilmek için bu TDI transport sürücüleri çalisir. Network adaptörün sürücüsü, NIC driver da bu NDIS standardi içinde çalistigi için onunla da standart fonksiyonlarla haberlesebiliriz ve gerektigi gibi networksel reassembly, ack ve retransmission gibi islemleri yapabiliriz.

Ve NDIS miniport sürücülerimiz vardir. Bunlar NDIS transportlari ve adaptörler arasi haberlesme için fonksiyonlari tablolarlar.

TDI da ancak eski ve legacy tanimli geçmektedir. Yerine gelen ve IPv6 destekleyen winsock kernel dir, WSK.
Socket tipi ve protokol bagimsiz çalisan, spesifik API leri ile erisilebilen WSK asenkron I/O da izin vermektedir. Yani çok basit örnek vermek gerekirse, üstte I/O Manager dan gelen IRP ü WSK ilgili transport protokol sürücüsüne paketlemek için aktarabilir. WSK datagram da kullanabilir ama connetionli baglanti da kullanabilir. Yukaridaki Winsock API lerde çift yönlü ve tek yönlü haberlesmenin karsiligidir.

Daha spesifik ihtiyaçlar için Windows filtering platform WFP API leri mevcuttur. Böylece network stackin herhangi bir yerinde paket isleminde interaksiyona girmek mümkün olur. Örnegin paketleri sayabilir, scan edebilir veya sadece monitör edebilirsiniz.
Bu API lerin karsiliginda da islemi yapan WFP callout sürücülerimiz mevcuttur.

Network API leri örnegin bilgisayar ismi olarak tanilan NetBIOS için de vardir. Burada netapi32.dll ve kernel tarafinda netbios.sys bize ilgili altyapiyi sunar. NetBIOS un protokolü netbios extended user interface NetBEUI protokolüdür ve NetBIOS semantiklerini tcp/ip protokolüne çeviren netbt.sys modülüdür. Örnegin yaziliminiz bir netbios name resolution yaptiginda, basitçe istek netapi32.dll üzerinden ve oradan ebetteki ntdll.dll üzerinden kerneldeki netbios.sys den komutlari tcpip.sys sürücüsüne vermeden, netbios emülatörü netbt.sys den geçer ve tcpip protol fonksiyonlarina çevrilirler.

NetBIOS dan daha önemli tabii ki DNS dir ve sadece DNS ile çözümleme yapilamazsa NetBIOS/WINS kullanilir. WINS de yoksa, NetBIOS kendisi çözümlemeyi üstlenir.

IPv6 ile yeni bir çözümleme protokolümüz de vardir: peer name resolution protocol PNRP. Bu hem DNS kullanabilir, hem de sunucusuz çalisabilir. Her kayit için çok daha fazla detay bilgi tutabilir ve güncellemeler real time dir. Yani DNS cache sorunu yok gibidir. Çözümlemesi dâhidir: detaya inmeden temelinde aslinda ilk olarak aradigimiz kaydin ID sini kimin tuttugunu bulmaya çalisiriz ve bunu dügüm noktalari üzerinden yapariz. Sonra yine dügüm noktalari üzerinden aradigimiz makineyi en geç yakinindaki benzer ID ler ile kestiririz. Hedefe mantiksal kestirme algoritmasi izlendigi için bunu sunucusuz da yapabiliriz. Yaklastikça aradigimiz makineyi taniyan bir makineye sonunda denk gelip hedefe ulasiriz. PNRP hakkinda detayli bilgi için kitaba bakmanizi öneririm.

OSI ile komponentler arasi iliskiyi de sayfa 1005 de görebilirsiniz ve bu belki yukaridaki detaylarin kafanizda birlesmesine yardimci olur.

Bütün komponentlerinin modüllerinin de farkli konfigürasyonlarda birbirleri ile düzgün çalismasini saglayan mantiga da Binding denir. Örnegin farkli networksel OS componentleri yüklü olabilir veya olmaya bilir, farkli sürücüler yüklü olabilir, network adaptörlerin gelismis ayarlarinin bazilarinda IPv6 seçili olmayabilir vs. Binding i HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Linkage altindaki Bind degerinde tutariz. En nihayetinde de bu bizim network stackini belirler. Yani komponentlerin olusturdugu OSI yapisinin kullanilan modüllerinin aralarinda düzgün çalisabilmeleri için ve stackin böylece düzgün olusturulabilmesi için ile ilgili degisken bilgileri registry de tutariz.

Böylelikle Windows OSI layer mantigini sunar ve her katmaninda yazilimsal müdahaleye izin verir.

Windows Networking teknolojilerin çok daha detayli özetini Windows Internals 5th ed. in 12 ci bölümü ‘Networking’ altinda bulabilirsiniz: https://technet.microsoft.com/en-us/sysinternals/bb963901
Okumanizi kesinlikle tavsiye ederim.

Basar Güner
Sr. Support Engineer, Microsoft

image