Sieciowe systemy plików wedlug Microsoft


1. Wstęp

Istnieją na świecie komputery, na których, zamiast Linuxa, zainstalowany jest system operacyjny firmy Microsoft. Ponieważ trochę tych komputerów jest, więc warto przyjrzeć się, jak zaimplementowano w Winowsie (a w konsekwencji, jak się za chwilę okaże, również w DOSie) sieciowy dostęp do plików.

Pierwsze co się rzuca w oczy to to, jaką gimnastykę Microsoft musiał wykonać, żeby zachować wsteczną kompatybilność, z rozwiązaniami, których korzenie sięgają początków lat 80. Właśnie ta dbałość o zgodność wstecz (konieczna z punktu widzenia marketingowego) jest źródłem skomplikowania i niezgrabności prezentowanej architektury.

Warto już na wstępie wspomnieć o tym, że w ramach świata Open Source, podejmowanych jest wiele inicjatyw, mających na celu stworzenie implementacji zgodnych ze standardami Microsoftu. I nie chodzi tu tylko i wyłącznie o słynna SAMBę, gdyż istnieje wiele innych projektów. Warto zwrócić uwagę na to, że wysiłki te stanowią jeden z istotnych czynników warunkujących popularność wolnego oprogramowania.

2. NetBIOS

Dawno temu, na początku lat 80, firma IBM, wraz z firmą Sytec stworzyły PC-Network. Było to jedno z pierwszych rozwiązań sprzętowych, umożliwiające połączenie komputerów osobistych w sieć lokalną (Żadnych ethernetów, czy token ringów wtedy jeszcze nie było). PC-Network był bardzo ograniczony - można było połączyć ze sobą zaledwie 80 jednostek (w jednej, płaskiej sieci). Dostawcy PC-Networku dostarczali użytkownikowi wszystkie odpowiednie komponenty hardware'owe, a oprócz tego dostarczali specjalny driver zwany NetBIOS (Network Basic Input/Output System). API dostarczane przez NetBIOS okazało się na tyle popularne, że powstała cała masa oprogramowania korzystającego z niego.

Z uwagi na powyższe, wraz z pojawieniem się zaawansowanych protokołów z prawdziwego zdarzenia, pojawiła się konieczność dostarczenia istniejącemu oprogramowaniu możliwości dalszego funkcjonowania. Dlatego też powstały implementacje netBIOS korzystające z protokołów takich jak DECnet, SNA, IPX/SPX oraz (oczywiście) TCP/IP. Tą ostatnią określa się mianem NBT.

NBT został udokumentowany w dwóch dokumentach RFC: RFC1001 oraz RFC1002 w 1987 (ten pierwszy opisuje ogólne koncepcje i metody, ten drugi to szczegółowa specyfikacja).

Wspomniane dokumenty opisują usługi jakie mają zapewnić implementacje NBT. Te usługi to: 2.1 Name Service

Przy użyciu tej usługi przypisuje się komputerom nazwy zrozumiałe dla ludzi. Są to właśnie te nazwy które widzimy, gdy przeglądamy otoczenie sieciowe w windowsie.
NetBIOSowa nazwa określa albo jeden, konkretny komputer, albo grupę (Workgroup - również można spotkać w otoczeniu sieciowym). Nazwy są maksymalnie długości 15. 16 bajt określa typ zasobu opisywanego nazwą - mówi o tym, jakich usług dostarcza określony komputer.

NetBIOSowy Name service przypomina w pewnym stopniu internetowy DNS (Domain Name Service) - w tym sensie, że tłumaczy zrozumiały dla człowieka ciąg znaków na identyfikator komputera zrozumiały dla protokołu niższego rzędu, jednak na tym podobieństwa się kończą.

Nie ma czegoś takiego jak hierarchia występująca w przypadku DNS (oddzielone "." części nazwy) - nazwa jest płaska - musi być unikalna w sieci netBIOS

Kolejną różnicą w porównaniu do DNSa jest to, że w DNSie adresy komputerów są ustalane na stałe, w scentralizowany sposób. W NetBIOSie za każdym razem jak komputer startuje, dokonuje rejestracji przypisania swojej nazwy do adresu (na przykład IP). Dodatkowo, możliwe jest wyrejestrowanie tego przypisania.
W przeciwieństwie do DNS nastawionego na wykorzystanie centralnego serwera nazw, który obsługuje prośby klientów zwracając adresy odpowiadające podanej nazwie, w NetBIOSie mamy do czynienia z dwoma sposobami zdobycia adresu dla podanej nazwy.
Komputery w sieci netBIOSowej mogą albo skorzystać z rozgłoszenia (broadcast - równoczesne nadawanie pakietów do wszystkich komputerów wsieci), albo z centralnego servera (zawanego NBNS - NetBIOS Name Server. Ale microsoft jakiś czas temu zaczął go nazywać WINS - Windows Internet Name Service).

Z uwagi na tą możliwość wyboru, każdy komputer w sieci NetBIOS musi być skonfigurowany żeby używać jednego z poniższych trybów:

2.2 Session Service

Sesja jest to akt wymiany danych pomiędzy dwoma aplikacjami korzystającymi z netBIOS. Sesja musi zapewniać pewność dostarczenia wysłanych pakietów, pakiety muszą dojść w tej samej kolejnośći w jakiej zostały wysłane. Sesja musi być dwukierunkowa ( full-duplex). Z punktu widzenia netBIOS nie ma znaczenia co zostaje przekazane w przesyłanych pakietach - chodzi o to, żeby można było zainicjować połączenie pomiędzy dwoma aplikacjami na komputerach o podanych nazwach (adresy uzyskuje się z name service) i korzystać z możliwości jakie daje sesja

W przypadku NBT (Czyli implementacji netBIOS w TCP/IP), zakłada się, że port 139 jest uzywany do stworenia netBIOSowej sesji. Jak wiadomo, TCP jest protokołem o poziom wyżej od IP (w hierarchi OSI) - zapewnia on właśnie sesyjność. Z tego powodu, w przypadku NBT niewiele trzeba dołożyć do TCP żeby uzyskać funkcjonalność netBIOS. Jedyna istotna różnica jest taka, że w przypadku TCP zakłada się pracę ze strumieniem danych - bez rozgraniczenia poszczególnych pakietów (choć oczywiście TCP realizowane jest również poprzez pakiety - enkapsulowane w pakietach IP). Aby uzyskać netBIOSowe pakiety, przed wysłaniem porcji danych dołącza się mały nagłówek z informacją o tym ile danych które za chwile przyjdą jest w ramach właśnie nadawanego pakietu.

2.3 Datagram Service

W przeciwieństwie do sesji, usługa datagramowa nie zapewnia bezpieczeństwa dostarczenia pakietów, jak również nie zapewnia kolejności. Wysłanie datagramów można porównać do wysłania listu (nie poleconego) - pewnie dojdzie, ale nie ma pewności.
Zaletą datagramów jest po pierwsze wydajność - nie ma dodatkowych kosztów jak w przpadku sesji. Dodatkowo, ze pomocą datagramów realizuje się rozgłoszenie - jeden datagram zostaje wysłany do wielu komputerów (na przykład w ramach grupy).

W przypadku NBT, zakłada się, że protokół UDP na porcie 138 powinien zostać użyty do realizacji datagram service. UDP zapewnia prawie taką samą funkcjonalność jak datagram service - są jednak pewne drobne różnice.
Ten problem jest również rozwiązany poprzez użycie małego nagłówka. Nagłówek ten zawiera 2 istotne informacje: nazwę nadawcy datagramu (Żeby serwer widział komu odpowiedzieć) oraz informację o tym, czy datagram netBIOSowy został pocięty na mniejsze kawałki żeby wysłać go przez UDP (Tak żeby można było posklejać).

2.4 Problemy i przyszłość

Wraz z windowsem 2000 dostarczono implementację CIFS (o którym za chwilę) bezpośrednio nad TCP/IP. Ciągle jednak większość komputerów na których działa windows korzysta z NBT aby uzyskać dostęp do zasobów takich jak pliki, czy drukarki.
Jest to pewnego rodzaju problem - komputery porozumiewają się za pomocą emulacji wirtualnego LANa (Local Area Network), który dawno już nie istnieje - ogranicza to w jakimś stopniu wydajność.

Dodatkowo, w implementacji WINS popełniono pewne problemy - tak, że jeżeli sieć netBIOSowa rozciąga się na wiele podsieci IP, to mogą wystąpić problemy przy nadawaniu w ramach grupy komputerów.

3. SMB/CIFS

SMB (Server Message Block), zwany również CIFS (Common Internet File System) jest protokołem służącym do realizacji współdzielenia plików w ramach LAN. Został stworzony na początku lat 80 przez Microsoft i Intela.

W skrócie, sposób działania CIFS jest następujący: klient wysyła żądanie do serwera. Żądanie to może dotyczyć np. otwarcia, czy czytania z pliku. Serwer otrzymuje pakiet, sprawdza czy żądanie jest poprawnie sformułowane, sprawdza uprawnienia klienta do plików, wykonuje żądanie i odsyła odpowiedź do klienta. Klient czyta odpowiedź i sprawdza, czy jest to to czego chciał.

Tak jak wspominałem, CIFS używa w większości przypadków netBIOSu aby realizować samą komunikację przez sieć. Może jednak być to zupełnie inny protokół - byleby zapewnił to co CIFSowi jest potrzebne do działania.

Czasami dokonuje się rozróżnienia pomiędzy CIFS i SMB w ten sposób, że SMB zapewnia podstawową funkcjonalność operowania na plikach, a CIFS to oprócz tego cały pakiet dodatkowych usług takich jak drukowanie sieciowe, czy przeglądanie otoczenia sieciowego przy użyciu tzw. Browse Servers.

Oto lista usług zapewnianych przez CIFS:
Część wymienionych cech jest dostępnych wyłącznie w najnowszej wersji protokołu (w szczególności Distributed Replicated Virtual Volumes).

Opisanie wszystkich cech CIFS wykracza zdecydowanie poza ramy tego opracowania - skupię się tu na opisaniu kilku wybranych, podstawowych cech.

3.1 Przegląd podstawowej komunikacji klient - serwer

Aby mieć dostęp do pliku na serwerze, klient wykonuje następujące czynności: Pierwszy z wymienionych punktów może wyglądać na przykład tak, że klient chce uzyskać dostęp do zasobu "\\komp\dokumenty\jakis.doc" - więc musi wydobyć nazwę komputera "komp", oraz ścieżkę do zasobu "\dokumenty\jakis.doc". Jeżeli ścieżka jest zmapowana na jakiś dysk (na przykład "\\komp\dokumenty" jest przypisane "do t:\"), to nazwa może być postaci "t:\jakis.doc". Nazwa może też być URLem - wtedy też trzeba wydobyć komputer i ścieżkę.

Następny krok może być zrealizowany na przykład za pomocą WINS (opisane wcześniej).

Teraz zaczyna się właściwa komunikacja. Może ona być na przykład następująca (Przykład zaczerpnięty ze specyfikacji protokołu):

Komenda klientaOdpowiedź serwera
SMB_COM_NEGOTIATEJest to pierwsza wiadomość, którą klient zawsze musi wysłać do serwera. W środku jest informacja o zestawie dialektów SMB jakie klient rozumie. Serwer wybiera sobie jeden dialekt i odsyła klientowi - tym dialektem będą się w przyszłości posługiwać.
SMB_COM_SESSION_SETUP_ANDXKlient wysyła swoją nazwę i informację uwierzytelniającą. Serwer zwraca UID - jednoznacznie identyfikujący tego klienta w kolejnych kontaktach z serwerem.
SMB_COM_TREE_CONNECT_ANDXKlient wysyła informację o tym do jakiego zasobu chce mieć dostęp. Serwer zwraca TID - identyfikujący ten zasób w kolejnych komendach.
SMB_COM_OPEN_ANDXTID identyfikował zasób - czyli na przykład katalog. Teraz klient wysyła ścieżkę relatywną w odniesieniu do zasobu (TID jest dołączony do tego komunikatu). Serwer zwraca FID - identyfikuje on konkretny plik i jest używany w kolejnych komunikatach.
SMB_COM_READKlient wysyła TID, FID, offset w ramach pliku, jak również ilość bajtów do przecytania, serwer zwraca odpowiednie dane.
SMB_COM_CLOSEKlient zamyka plik identyfikowany przez TID/FID. Serwer zwraca kod sukcesu.
SMB_COM_TREE_DISCONNECTKlient 'odpina' zasób reprezentowany przez TID.

Warto zwrócić na postfixy _ANDX - jest to mechanizm batchowego wysyłania wielu wiadomości - tak naprawdę te wiadomości które w przykładzie miały z tyłu _ANDX zostaną wysłane tylko raz.

3.2 Opportunistic Locks

Jest to mechanizm pozwalający poprawić wydajność korzystania z plików. Jeżeli klient może założyć, że plik który sobie pobrał i trzyma lokalnie jest aktualny, to nie musi pobierać danych z serwera. Podobnie, jeżeli może założyć, że może lokalnie pisać do pliku, również nie musi komunikować się z serwerem.

Są trzy typy oplocków:

Oto przykład komunikacji z exclusive oplockiem(Przykład zaczerpnięty ze specyfikacji protokołu):

Klient AKlient B<->Serwer
Open("plik")   ->  
    <- Open OK. Exclusive oplock granted
<locks,writes>      
read(large)   ->  
    <- read data
<reads from read ahead>      
  Open("plik") ->  
    <- oplock break to A
lock(s)   ->  
    <- lock(s) response(s)
write(s)   ->  
    <- write(s) response(s)
close or oplock ack   ->  
    <- open response to A

Działa to mniej więcej tak, że klient A mając exclusive locka może robić co chce z plikiem. Do czasu aż klient B zechce otworzyć ten sam plik. Wtedy serwer informuje klienta A, że koniec zabawy. Klient A musi teraz dokonać synchronizacji swojego stanu pliku ze stanem po stronie serwera (musi poprawić stan i atrybuty pliku, jak również wysłać informacje o lockach w ramach pliku). Następnie albo zamyka plik, albo wysyła potwierdzenie. Wtedy serwer może wysłać do B informację o otwarciu pliku. Jeżeli B nie będzie zmieniał pliku, to A może dostać Level II oplock i dalej korzystać ze swojej lokalnej kopii pliku.

3.3 Header SMB

Poniżej zamieszczam header wiadomości SMB wraz z komentarzami:

typedef unsigned char UCHAR; // 8 unsigned bits 

typedef unsigned short USHORT; // 16 unsigned bits 

typedef unsigned long ULONG; // 32 unsigned bits 

 

typedef struct { 

   ULONG LowPart; 

      LONG HighPart; } 

LARGE_INTEGER; // 64 bits of data 

 

typedef struct { 

   UCHAR Protocol[4]; // Contains 0xFF,'SMB' UCHAR 

   Command; // Command code 

   union { 

       struct { UCHAR ErrorClass; // Error class 

                UCHAR Reserved; // Reserved for future use 

                USHORT Error; // Error code 

       } DosError; 

       ULONG Status; // 32-bit error code 

   } Status; 

   UCHAR Flags; // Flags 

   USHORT Flags2; // More flags 

   

   union { 

      USHORT Pad[6]; // Ensure section is 12 bytes long 

      struct { USHORT PidHigh; // High part of PID 

               UCHAR SecuritySignature[8]; // reserved for security 

      } Extra; 

   }; 

   USHORT Tid; // Tree identifier 

   USHORT Pid; // Caller's process id 

   USHORT Uid; // Unauthenticated user id 

   USHORT Mid; // multiplex id 

   UCHAR WordCount; // Count of parameter words 

   USHORT ParameterWords[ WordCount ]; // The parameter words 

   USHORT ByteCount; // Count of bytes 

   UCHAR Buffer[ ByteCount ]; // The bytes 

} SMB_HEADER;



Jest jeszcze bardzo wiele spraw które warto wiedzieć o CIFS - informacje można znaleść między innymi w MSDN, jak również w niezależnym opracowaniu CIFS Explained.

4. CIFS a Open Source

Istnieje wiele inicjatyw w ramach Open Source mających na celu implementację CIFS.
Inicjatywy te są moim zdaniem jednym z głównych powodów sukcesu Linuxa jako serwera w wielu firmach - stanowi on bardzo konkurencyjną propozycję jako serwer plików w firmach sektora MSP.

W ramach wspomnianych projektów warto oczywiście wspomnieć przede wszystkim projekt SAMBA - bardzo dojrzałą implementację SMB.

Jednak SAMBA znajduje zastosowanie jako serwer plików - a ważne jest żeby linux mógł konkurować jako równoprawny gracz na rynku desktopów. Jednym warunkiem sukcesu linuxa na biurku jest możliwość współuczestniczenia w otoczeniu sieciowym wraz z komputerami windowsowymi - czyli musi istnieć wygodny sposób przeglądania otoczenia sieciowego w linuxie.
To jest właśnie geneza SMBFS - części jądra zapewniającej możliwość montowania zasobów windowsowskich.

Wśród pozostałych projektów warto wspomnieć o libsmbclient - bibliotece klienckiej SMB oraz Filesys:SmbClient - moduł perlowski umożliwiający korzystanie zlibsmbclient.

Sharity-Light jest opartą na SMBFS implementacją klienta operującą poza jądrem.


Bibliografia

CIFS Explained, CodeFX
RFC1001, RFC1002
MSDN - "Common Internet File System (CIFS/1.0) Protocol - Preliminary Draft" - Network Working Group, Paul J. Leach, Dilip C. Naik
SMB-HOWTO