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:
- name service
- session service
- datagram service
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:
- Samo rozgłoszenie (b-node)
- Sam WINS (p-node)
- Najpierw rozgłoszenie, a jak się nie uda, to WINS (m-node)
- WINS, a jak nie odpowiada to rozgłoszenie (h-node)
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:
- Dostęp do plików - open/close/read/write/seek.
- Lockowanie plików i rekordów - klient może zapenić sobie wyłączność
dostępu do pliku.
- Caching, read-ahead, write-behind - o ile nikt nie pisze do pliku, możliwe
jest korzystanie z niego lokalnie bez potrzeby odwoływania sie do serwera.
- Informowanie o zmianie pliku/katalogu - klient rejestruje zainteresowanie tymi informacjami.
- Negocjowanie wersji protokołu - jest ich sporo i trzeba wybrać ten któego mają używać uczestnicy komunikacji.
- Rozszerzone atrybuty - CIFS zapewnia dodatkowe atrybuty plików, oprócz tych które
normalnie zapewnia lokalny FS.
- Distributed Replicated Virtual Volumes - można tworzyć drzewa katalogowe rozciągające
się na wiele serwerów, w ten sposób, że klientowi jawią się jako jeden serwer. Dzięki
temu możliwe są też replikacje zapewniające load balancing (czyli automatyczne przekierowywanie
klientów do mniej obciążonego serwera - z tymi samymi danymi), oraz transparentne bezpieczeństwo
(czyli jeden serwer pada, ale drugi wciąż działa, a klient dalej pracuje).
- Niezależność od usługi nazewnictwa - można na przykład użyć DNS.
- Batched requests - żeby poprawić wydajność, niektóre żądania można wrzucić w jedną wiadomość.
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:
- Parsuje podaną nazwę zasobu, tak żeby wydobyć nazwę serwera i nazwę samego zasobu.
- Korzysta z nazwy serwera aby otrzymać adres sieciowy serwera.
- Jeżeli wcześniej nie nawiązał połączenia z serwerem, to robi to teraz.
- Wymienia się wiadomościami z serwerem.
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 klienta | Odpowiedź serwera |
SMB_COM_NEGOTIATE | Jest 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_ANDX | Klient 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_ANDX | Klient 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_ANDX | TID 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_READ | Klient wysyła TID, FID, offset w ramach pliku, jak również ilość bajtów do przecytania, serwer zwraca odpowiednie dane. |
SMB_COM_CLOSE | Klient zamyka plik identyfikowany przez TID/FID. Serwer zwraca kod sukcesu. |
SMB_COM_TREE_DISCONNECT | Klient '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:
- Level II - jeżeli jest założony, to znaczy, że jest wielu klientów korzystających
z pliku, ale żaden jeszcze go nie zmodyfikował. Klient może użyć scachowanej informacji,
albo dokonać read-ahead żeby pobrać fragment pliku 'na zapas'
- Exclusive - klient jest jedynym który ma ten plik otwarty. Może działać na
nim lokalnie tak jak mu się podoba - przy zamykaniu powinien wysłać zmiany do serwera.
- Batch - to samo co w exclusive, ale lock rozciąga się nawet poza granice zamknięcia pliku
Oto przykład komunikacji z exclusive oplockiem(Przykład zaczerpnięty ze specyfikacji protokołu):
Klient A | Klient 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