Virtlab:Konzolový server
Z VirtlabWiki
Verze z 14:51, 26. 1. 2008 Kuc274 (Diskuse | příspěvky) (→Volání funkcí) ← Předchozí porovnání |
Verze z 14:59, 26. 1. 2008 Kuc274 (Diskuse | příspěvky) (→Struktura zdrojových souborů pro zařízení a domény) Následující porovnání → |
||
Řádka 12: | Řádka 12: | ||
[[Image:Cserver_sekvenceFunkci2.png|center|400px|"Funkce volane z obsluhuj_klienta()"]] | [[Image:Cserver_sekvenceFunkci2.png|center|400px|"Funkce volane z obsluhuj_klienta()"]] | ||
- | == Struktura zdrojových souborů pro zařízení a domény == | + | == Struktura zdrojových souborů == |
- | + | Výše uvedené diagramy popisovaly základní funkce obsažené v základním zdrojovém souboru '''server.c''' + pár funkcí z [[Virtlab:Konzolový server/Zařízení a domény|dalších zdrojových souborů]]. | |
- | === devices.c (.h) === | + | |
- | používané struktury (zdrojový kód po mírné úpravě): | + | |
- | //popis jednoho zarizeni | + | |
- | struct DEVICE_T { | + | |
- | char devicename[DEV_ID_MAX_LENGTH]; | + | |
- | int device_type; | + | |
- | int fd_for_tutor; | + | |
- | int fd_for_client; | + | |
- | union { | + | |
- | char serial_port_path[MAX_SERIAL_PATH]; | + | |
- | TELNET_CONN telnet_data; | + | |
- | }; | + | |
- | }; | + | |
- | //polozka zretezeneho seznamu zarizeni | + | |
- | struct DEVICES_T { | + | |
- | DEVICE_T data; | + | |
- | struct devices_t *next; | + | |
- | }; | + | |
- | + | ||
- | Přehled funkcí: | + | |
- | DEVICES_T *add_device(DEVICE_T device, DEVICES_T **devs); | + | |
- | int load_devices(const char *devs_file, DEVICES_T **devs); | + | |
- | DEVICE_T *find_device_by_name(const char* devname, DEVICES_T *devs); | + | |
- | int split_dev_id_location(char *dev_at_loc, char **dev, char **loc); | + | |
- | + | ||
- | Funkce '''add_device''' přidá zařízení do seznamu. Prvnim parametrem je popis pridavaneho zarizeni, druhym pak ukazatel na "prvni zarizeni v aktualnim seznamu". Nove pridane zarizeni se zaradi na zacatek seznamu. Funkce vraci ukazatel na seznam. | + | |
- | + | ||
- | Funkce '''load_device''' nacita z textoveho souboru (devs_file) popisy zarizeni. Rozlisi, zda je zarizeni pripojeno seriovou linkou nebo pomoci Ethernetu. Tuto i dalsi informace ulozi do struktury pro popis zarizeni (DEVICE_T), kterou nasledne zakomponuje do seznamu zarizeni (pomoci funkce add_device ). | + | |
- | * ''Soubor oznaceny jako "devs_file" je konfiguracni soubor, ktery se standartne nachazi v '''/etc/virtlab''' a ma nazev '''cons-devices.conf'''.'' | + | |
- | * Tato funkce je volana skoro na zacatku funkce '''main''' v souboru '''server.c'''. | + | |
- | + | ||
- | + | ||
- | Funkce '''find_device_by_name''' hleda nazev specifikovany parametrem ''devname'' v seznamu zarizeni (specifikovan druhym parametrem). Jestlize zarizeni najde, vraci odkaz na strukturu, ktera jej popisuje. V opacnem pripade vraci odkaz na NULL. | + | |
- | + | ||
- | Funkce '''split_dev_id_location''' rozdeli vstupni retezec ''dev_at_loc'' na dve casti. Prvni odkazuje na jmeno zarizeni a druha na nazev lokality. (Obe ale realne pracuji se stejnym retezcem, jen ukazuji do jine jeho casti - nic se nekopiruje.) | + | |
- | + | ||
- | === domain.c (.h) === | + | |
- | DOMAINS_T *add_domain(DOMAIN_T domain, DOMAINS_T **doms); | + | |
- | int load_domains(const char *doms_file, DOMAINS_T **doms); | + | |
- | DOMAIN_T *find_domain_by_name(const char* domname, DOMAINS_T *doms); | + | |
- | DOMAIN_T *find_domain_by_ip(in_addr_t *ip, DOMAINS_T *doms); | + | |
- | + | ||
- | Práce s doménami je velice podobná práci se zařízeními. Jsou k dispozici opět čtyři funkce, odlišný význam má pouze ta poslední (find_domain_by_ip). Má za úkol najít doménu v seznamu, ovšem na základě IP adresy. | + | |
- | + | ||
- | * ''Soubor oznaceny jako "doms_file" je konfiguracni soubor, ktery se standartne nachazi v '''/etc/virtlab''' a ma nazev '''cons-servers.conf'''.'' | + | |
- | * Tato funkce je volana skoro na zacatku funkce '''main''' v souboru '''server.c'''. | + | |
- | + | ||
- | Doména může být typu '''local''' nebo '''remote'''. | + | |
- | + | ||
== Struktura hlavního souboru - server.c (.h) == | == Struktura hlavního souboru - server.c (.h) == |
Verze z 14:59, 26. 1. 2008
Obsah |
Úkoly konzolového serveru
Jeho úkolem je zprostředkovat přístup k sériovým nebo telnetovým konzolím síťových zařízení prostřednictvím jednoduchého protokolu nad TCP/IP. Je využíván Java Appletem, který běží ve webovém ovládacím rozhraní, což umožňuje uživateli jednoduchý přístup k síťovým zařízením. Zároveň slouží i jako proxy server, který zprostředkovává přístup k zařízením, která jsou připojena ke vzdáleným konzolovým serverům, kam nemá místní uživatel přímý přístup. Také prostřednictvím speciálního PHP skriptu ověřuje, jsou-li požadavky uživatele oprávněné a tím konzoly prvků zabezpečuje od neautorizovaného přístupu.
Popis implementace
(pozor: nejde o skutecny sekvencni diagram)
Zdrojový soubor server.c obsahuje hlavní funkci (main), která po úvodní inicializaci volá v nekonečném cyklu funkci obsluhuj_klienta().
Ve funkci obsluhuj_klienta() jsou pak načteny 4 řádky parametrů od klientského apletu. Tyto parametry jsou ověřeny pomocí funkce check_applet_args() a v případě, že klient chce takto přistupovat k prvku, který má korektně na danou dobu rezervován, vrátí funkce čas do konce rezervace (v sekundách). (V opačném případě vrací nulu a obsluhuj_klienta() následně skončí.)
V případě úspěchu se nastaví alarm() a hned potom se dostane ke slovu funkce open_dev_fd(), která ověří, jestli zařízení již není používáno jiným apletem. Není-li, zamkne jej pro výlučný přístup a vrátí na něj deskriptor.
Struktura zdrojových souborů
Výše uvedené diagramy popisovaly základní funkce obsažené v základním zdrojovém souboru server.c + pár funkcí z dalších zdrojových souborů.
Struktura hlavního souboru - server.c (.h)
Handler na SIGPIPE
static void sig_pipe(int signo);
check_applet_args
Funkce, ktera zkontroluje platnost parametru poslanych appletem oproti webovemu serveru
- V případě, že aplet s těmito parametry má právo přistupovat k požadovanému zařízení, funkce vrátí počet sekund do konce rezervace (bez "patičky")
- V opačném případě vrátí hodnout 0
Vlastní kontrolu parametrů provádí externí skript check-applet-args.sh, který výsledek zapíše do souboru v /tmp/. Z něj pak druhý proces hodnotu převezme. (Druhým procesem je myšlen rodičovský proces - po volání funkce fork)
# define applet_checker "./check-applet-args.sh" # define result_basefile "/tmp/appletchecker" int check_applet_args(char* sid, char* sip, char* did, char* tm, char *resid) { ... fork(); //child: execlp(applet_checker, applet_checker, sid, sip, did, tm, resid, result_file, (char*)(NULL)); //parent: //prevezmi hodnotu ze souboru a pak ji predej jako svou navratovou hodnotu pomoci return result; ... }
open_dev_fd
funkce, ktera otevre seriovy port/TCP stream pro cteni
int open_dev_fd(const char *_dev_id, int *target_is_cserver, int tutor, int* fd_to_tutor) {
T.K. - to uz je (doufam) stara informace: ??? // posledni pismeno cesty je podle porty.h
- Funkce nejdříve převezme první argument a rozdelí jej na část pro zařízení a část pro lokalitu. Následně ověří, zda lokalita existuje a je dostupná. Stejnětak ověří i existenci zařízení. Podle typu zařízení a hlavně jeho umístění se rozhoduje, zda se s ním bude komunikovat přes sériový port, nebo přes TCP spojení (Jde-li o vzdálené zařízení.)
- Nechápu tu ale, proc je jako typ zarizeni povazovana i moznost DEVICE_TUTOR
Nastavení FD jako NONBLOCKING
void set_nonblocking(int fd);
Nastavení FD jako BLOCKING
void set_blocking(int fd);
close_tutor
Rekne tutorovi, ze se od nej odpojuje
void close_tutor(int fd_tutor) { set_nonblocking(fd_tutor); write(fd_tutor, MSG_IM_DYING, strlen(MSG_IM_DYING)); set_blocking(fd_tutor); }
close_fd_dev
Zavre socket zarizeni, je-li od tutora ke klientovi, posle jen zpravu o ukonceni
void close_fd_dev(int fd, int is_tutor) { if(is_tutor) { close_tutor(fd); } else close(fd); }
get_timestamp
vrati casove razitko
char *get_timestamp(void);
get_line_from_socket
Funkce čte ze soketu, který dostane jako první parametr. Přečte nejvýše tolik znaků, kolik udává třetí parametr a výsledek uloží do parametru dvě. Čtení končí, narazí-li na znaky CR/LF nebo načte-li maximální počet znaků (třetí parametr).
main
Hlavni funkce pro cely Konzolovy server.
Postupně provádí tyto akce:
- nahraje soubor s doménami
- nahraje soubor se zařízeními
- vytvoří socket pro příjem spojení od klientů
- a nastaví některé jeho parametry
- funkcí bind jej pojmenuje
- funkcí listen bude očekávat spojení od klientů
- následuje "nekonečná" smyčka, ve které se vlastně pro každého připojeného klienta vytvoří nový proces, jehož úkolem je obsluha tohoto klienta. Tu zajišťujeme funkcí obsluhuj_klienta
obsluhuj_klienta
Smyslem je číst znaky od klientského apletu a předávat je cílovému prvku (např. CISCO) a také znaky od zařízení předávat klietskému apletu.
Implementace zakázaných příkazů
Virtuální laboratoř funguje zcela automaticky. Po vypršení času rezervovaného jedním studentem se smaže jím vytvořená konfigurace a síťové prvky se připraví pro práci dalšímu uživateli. Tohle by nebylo možné, kdyby studenti mohli zadávat do zařízení například libovolná hesla, která by pak byla vyžadována i pro smazání konfigurace.
Některé příkazy bylo tedy nutné zakázat.