Do spisu tresci tematu 9

9.2.2 Portmapper




Spis tresci


Wprowadzenie

Aby wywolac odlegla procedure (usluge) kllient powinien otrzymac jej adres. W tym celu komunikuje sie z demonem portmappera dzialajacym na zdalnym komputerze. Demon ten zawsze korzysta z portu o numerze 111. Portmapper dysponuje lista zarejestrowanych uslug z odpowiadajacymi im numerami portow. Dane te przechowuje w odpowiednich strukturach danych:

Struktury

- Glowna struktura portmappera jest lista, w ktorej trzymane sa numery programow i wersji z przypisanymi im numerami portow
struct pmaplist { 
    struct pmap pml_map;        /* struktura zawierajaca dane
    struct pmaplist *pml_next;  /* wskaznik do nastepnej
    }; 
, gdzie struktura pmap wyglada nastepujaco:
struct pmap { 
long unsigned pm_prog;     /* numer programu
long unsigned pm_vers;     /* numer wersji
long unsigned pm_prot;     /* rodzaj protokolu
long unsigned pm_port;     /* numer portu
}; 

Funkcje

Do komunikacji z portmapperem wykorzystujemy nastepujace funkcje:

pmap_getmaps()

struct pmaplist *pmap_getmaps(addr) 
    struct sockaddr_in *addr;   /* adres internetowy komputera
Funkcja ta zwraca liste zarejestrowanych uslug (program,wersja), wraz z przypisanymi im numerami portow, na komputerze o podanym adresie (moze to byc serwer zdalny lub lokalny). Wskaznik do tej struktury przechowywany jest na zmiennej globalnej serwera "pmaplist".

pmap_set()

bool_t pmap_set(prognum,versnum,protocol,port) 
    u_long prognum   /* numer programu 
    u_long versnum   /* numer wersji 
    int protocol     /* IPPROTO_UDP lub IPPROTO_TCP 
    u_short port     /* numer portu 
Dzieki tej funkcji mozemy przypisac numer portu do naszej nowo rejestrowanej uslugi. Na poczatku pobieramy adres naszego komputera przy uzyciu funkcji getmyaddress(), potem tworzymy klienta udp podane parametry wpisujemy do struktury parms typu struct pmap i wywolujemy
CLNT_CALL(client,PMAPPROC_SET,xdr_pmap,&pmap,xdr_bool,&result,
          tottimeout), 
ktora to fukcja kmomunikuje sie z naszym lokalnym portmapperem. Sprawdza on czy dana funkcja moze zostac zarejestrowana, jesli tak to zwraca kod sukcesu, wpp kod bledu.

pmap_unset()

bool_t pmap_unset(prognum,versnum) 
    u_long prognum    /* numer programu 
    u_long versnum    /* numer wersji 
Podobnie jak funkcja pmap_set z tym, ze funkcja CLNT_CALL wywolywana jest z parametrem PMAPPROC_UNSET.

pmap_getport()

u_short pmap_getport(address,prognum,versnum,protocol)
    struct sockaddr_in address   /*adres serwera 
    u_long prognum               /* numer programu 
    u_long versnum               /* numer wersji 
    int protocol                 /* IPPROTO_UDP lub IPPROTO_TCP 
Przy pomocy funkcji htons(PMAPPORT) ustawia zmmienna sin_port w adresie serwera na numer portu portmapera, tworzy samego klienta przy pomocy clntudp_bufcreate, wywoluje CLNT_CALL z parametrem PMAPPROC_GETPORT i ta juz wszystko zalatwia.

rmt_call()

enum clnt_stat 
     pmap_rmtcall(addr,prog,vers,proc,xdrargs,argsp,xdrres,resp,tout,port_ptr)
        struct sockaddr_in address /*a dres serwera 
	u_long prog,vers,proc      /* numer programu,wersji,procedury
	xdrproc_t xdrargs,xdrres   /* filtry xdr do obslugi danych
                                   /* nadawanych i przyjmowanych 
        caddr_t argsp,resp         /* wskazniki do argumentow funkcji 
                                   /* i do bufora na wynik 
        struct timeval tout        /* maksymalny czas oczekiwannia na odpowiedz  
Funkcja do zdalnego wywolywania procedury, sama przeszukuje mape zarejestrowanych portow, a nastepnie wywoluje zadana procedure, pozwala ona programowi przejrzec liste portow i procedur, i automatycznie wywolac zadana procedure w jednym kroku (funkcja dziala tylko dla protokolu udp). Poczatek jak w getport, tworzy klienta clntudp_create i wywoluje CLNT_CALL z PMAPPROC_CALLIT i ta znowu wszystko zalatwia. Wszystkie parametry typu PMAPPROC_xxx dla funkcji CLNT_CALL sa zmiennymi typu u_long. Po nich to portmaper rozpoznaje jakiej uslugi zyczy sobie od niego klient, z tych wywolan ciekawe jest PMAPPROC_CALLIT.

Dzialanie portmappera

Demon portmappera zaimplementowany jest w pliku portmap.c. Jest to serwer rpc wykonujacy funkcje reg_service(). Przydziela on sobie 111 numer portu oraz otwiera dwa wejscia jedno dla protokolu UDP drugie dla protokolu TCP, nastepnie wywoluje funkcje svc_register() i rejestruje jako swoja usluge funkcje reg_service, w ktorej to zaimplementowane sa wywolania nastepujacych funkcji (jako numery uslug - typu u_long):
#define PMAPPROC_NULL       ((u_long)0) 
#define PMAPPROC_SET        ((u_long)1) 
#define PMAPPROC_UNSET      ((u_long)2) 
#define PMAPPROC_GETPORT    ((u_long)3) 
#define PMAPPROC_DUMP       ((u_long)4) 
#define PMAPPROC_CALLIT     ((u_long)5)
Dla wywolania PMAPPROC_CALLIT wykonuje sie funkcje callit() w ktorej to nastepuje pobranie argumentow do zdalnej procedury. O ile dana procedura jest zarejestrowana to portmapper wywoluje ja na lokalnnym serwerze. W tym celu tworzy nowego klienta i wywoluje funkcje fork. Proces potomny zajmuje sie wykonaniem uslugi, a sam demon dziala dalej czekajac na kolejne zadania. Jezeli wszystko poszlo dobrze to proces potomny wysyla wynik wykonania procedury do kllienta korzystajacego z uslugi.

Bibliografia

  1. Biblioteka LIBC, pliki: ./rpc/*
  2. Plik: portmap.c
  3. R. Stevens: ,,Programowanie zastosowan sieciowych''
  4. M. Gabbasi, B. Dupouy: ,,Przetwarzanie rozproszone w systemie UNIX''


Autor: Pawel Glebocki