This shows you the differences between two versions of the page.
so2:laboratoare:lab10:exercitii [2018/04/26 10:50] ionel.ghita |
so2:laboratoare:lab10:exercitii [2019/04/23 23:03] (current) constantin.ghioc [4. [2p] Acceptarea unei conexiuni în kernel space] |
||
---|---|---|---|
Line 12: | Line 12: | ||
==== Pregătirea scheletului de laborator ==== | ==== Pregătirea scheletului de laborator ==== | ||
+ | |||
+ | Pentru rezolvarea laboratorului trebuie sa activam suportul de netfilter din kernel. In meniul deschis cu ''make menuconfig'' | ||
+ | activati optiunea ''Networking support/Networking options/Network packet filtering framework (Netfilter)''. | ||
Scheletul de laborator este generat din sursele din directorul ''tools/labs/templates''. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda: | Scheletul de laborator este generat din sursele din directorul ''tools/labs/templates''. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda: | ||
Line 79: | Line 82: | ||
- În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului. | - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului. | ||
- În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ''~/so2/linux/tools/labs''. | - În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ''~/so2/linux/tools/labs''. | ||
- | - În al treilea tab de terminal accesăm directorul ''~/so2/linux/'' cu sursele nucleului unde putem folosi [[:so2:laboratoare:lab01#cscope|Vim și cscope]] pentru parcurgerea codului sursă. | + | - În al treilea tab de terminal accesăm directorul ''~/so2/linux/'' cu sursele nucleului unde putem folosi [[:so2:laboratoare:lab01#cscope|Vim și cscope]] pentru parcurgerea codului sursă.<code> |
student@eg106-pc:~$ netcat -lup 6666 | student@eg106-pc:~$ netcat -lup 6666 | ||
</code> | </code> | ||
Line 117: | Line 120: | ||
Portul TCP sursă este, în antentul TCP, în formatul [[http://en.wikipedia.org/wiki/Byte_order#Endianness_in_networking|network byte-order]]. Parcurgeți secțiunea [[:so2:laboratoare:lab10#conversii|Conversii]]. Folosiți [[http://lxr.free-electrons.com/source/include/linux/byteorder/generic.h?v=4.9#L141|ntohs]] pentru conversie. | Portul TCP sursă este, în antentul TCP, în formatul [[http://en.wikipedia.org/wiki/Byte_order#Endianness_in_networking|network byte-order]]. Parcurgeți secțiunea [[:so2:laboratoare:lab10#conversii|Conversii]]. Folosiți [[http://lxr.free-electrons.com/source/include/linux/byteorder/generic.h?v=4.9#L141|ntohs]] pentru conversie. | ||
- | Pentru testare folosiți fișierul ''1-2-netfilter/user/test-1.sh''. Testul generează o conexiune către stația locală (pe ''localhost''), conexiune ce va fi interceptată și afișată de modulul de kernel. Scriptul este copiat pe mașina virtuală la ''make copy'' doar dacă este marcat ca executabil. | + | Pentru testare folosiți fișierul ''1-2-netfilter/user/test-1.sh''. Testul generează o conexiune către stația locală (pe ''localhost''), conexiune ce va fi interceptată și afișată de modulul de kernel. Scriptul este copiat pe mașina virtuală la ''make copy'' doar dacă este marcat ca executabil. Scriptul folosește utilitarul compilat static ''netcat'' din ''skels/networking/netcat''; acest executabil trebuie să aibă permisiuni de execuție. |
După rulare ar trebui să obținem un output similar celui de mai jos:<code> | După rulare ar trebui să obținem un output similar celui de mai jos:<code> | ||
Line 143: | Line 146: | ||
Pentru testare folosiți scriptul ''1-2-netfilter/user/test-2.sh''. | Pentru testare folosiți scriptul ''1-2-netfilter/user/test-2.sh''. | ||
- | Acest script are nevoie de compilarea fișierului ''1-2-netfilter/user/test.c'' în executabilul ''test''. Compilarea se face automat pe sistemul fizic la rularea comenzii ''make build''. Scriptul de testare este copiat pe mașina virtuală doar dacă este marcat ca executabil. | + | Acest script are nevoie de compilarea fișierului ''1-2-netfilter/user/test.c'' în executabilul ''test''. Compilarea se face automat pe sistemul fizic la rularea comenzii ''make build''. Scriptul de testare este copiat pe mașina virtuală doar dacă este marcat ca executabil. Scriptul folosește utilitarul compilat static ''netcat'' din ''skels/networking/netcat''; acest executabil trebuie să aibă permisiuni de execuție. |
În urma rulării testului veți obține un output similar celui de mai jos:<code> | În urma rulării testului veți obține un output similar celui de mai jos:<code> | ||
Line 154: | Line 157: | ||
Testul comandă filtrarea pachetelor întâi către adresa IP ''127.0.0.1'' și apoi către adresa IP ''127.0.0.2''. Primul pachet de inițiere de conexiune (către ''127.0.0.1'') este interceptat și afișat de filtru, în vreme ce al doilea (către ''127.0.0.2'') nu este interceptat. | Testul comandă filtrarea pachetelor întâi către adresa IP ''127.0.0.1'' și apoi către adresa IP ''127.0.0.2''. Primul pachet de inițiere de conexiune (către ''127.0.0.1'') este interceptat și afișat de filtru, în vreme ce al doilea (către ''127.0.0.2'') nu este interceptat. | ||
- | |||
==== 3. [2p] Socket TCP în starea listening ==== | ==== 3. [2p] Socket TCP în starea listening ==== | ||
Line 184: | Line 186: | ||
Extindeți modulul de la exercițiul anterior pentru a permite acceptarea unei conexiuni din exterior (nu trebuie transmis mesaj, doar acceptată o nouă conexiune). Trebuie completate zonele marcate cu ''TODO 2''. | Extindeți modulul de la exercițiul anterior pentru a permite acceptarea unei conexiuni din exterior (nu trebuie transmis mesaj, doar acceptată o nouă conexiune). Trebuie completate zonele marcate cu ''TODO 2''. | ||
- | Parcurgeți secțiunile [[:so2:laboratoare:lab10#operatii_asupra_structurii_socket|Operații asupra structurii socket]] și [[:so2:laboratoare:lab10#structura_proto_ops|Structura proto_ops]] din laborator. Pentru echivalentul ''accept'' în kernel-space, consultați handler-ul de apel de sistem [[http://lxr.free-electrons.com/source/net/socket.c?v=4.9#L1418|sys_accept4]]. Urmăriți în implementarea [[http://lxr.free-electrons.com/source/net/socket.c?v=4.9#L1418|sys_accept4]] apelul ''%%sock->ops->accept%%''. Folosiți ''0'' ca valoarea pentru ultimul argument (''flags''). | + | Parcurgeți secțiunile [[:so2:laboratoare:lab10#operatii_asupra_structurii_socket|Operații asupra structurii socket]] și [[:so2:laboratoare:lab10#structura_proto_ops|Structura proto_ops]] din laborator. Pentru echivalentul ''accept'' în kernel-space, consultați handler-ul de apel de sistem [[http://lxr.free-electrons.com/source/net/socket.c?v=4.15#L1553|sys_accept4]]. Urmăriți în implementarea [[https://elixir.bootlin.com/linux/v4.15/source/drivers/staging/lustre/lnet/lnet/lib-socket.c#L513|lnet_sock_accept]] cum este folosit apelul ''%%sock->ops->accept%%''. Folosiți ''0'' ca valoarea pentru penultimul argument (''flags'') și ''false'' pentru ultimul argument (''kern''). |
+ | |||
+ | <note tip> | ||
+ | Socket-ul nou creat (''new_sock'') trebuie creat cu apelul [[https://elixir.bootlin.com/linux/v4.15/source/net/socket.c#L1069|sock_create_lite]] și apoi îi trebuie configurate operațiile folosind<code> | ||
+ | newsock->ops = sock->ops; | ||
+ | </code> | ||
+ | </note> | ||
Afișați adresa și portul socket-ului destinație. Pentru a afla numele peer-ului unui socket (adresa sa), consultați handler-ul de apel de sistem [[http://lxr.free-electrons.com/source/net/socket.c?v=4.9#L1587|sys_getpeername]]. | Afișați adresa și portul socket-ului destinație. Pentru a afla numele peer-ului unui socket (adresa sa), consultați handler-ul de apel de sistem [[http://lxr.free-electrons.com/source/net/socket.c?v=4.9#L1587|sys_getpeername]]. | ||
Line 193: | Line 201: | ||
Ultimul argument al funcției ''%%sock->ops->getname%%'' va fi ''1'', însemnând că dorim aflarea de infomații despre capătul destinație (//remote end// sau //peer//). | Ultimul argument al funcției ''%%sock->ops->getname%%'' va fi ''1'', însemnând că dorim aflarea de infomații despre capătul destinație (//remote end// sau //peer//). | ||
- | Afișați adresa peer-ului (indicată de variabila ''raddr'') folosind macro-ul ''print_sock_address''. | + | Afișați adresa peer-ului (indicată de variabila ''raddr'') folosind macro-ul ''print_sock_address()'' definit mai sus în fișier. |
</note> | </note> | ||
Line 204: | Line 212: | ||
==== 5. [3p] Socket UDP sender ==== | ==== 5. [3p] Socket UDP sender ==== | ||
- | Creați un modul de kernel care creează un socket UDP și transmite mesajul din macro-ul %%MY_TEST_MESSAGE%% pe socket către adresa loopback pe portul ''60001''. | + | Creați un modul de kernel care creează un socket UDP și transmite mesajul din macro-ul ''MY_TEST_MESSAGE'' pe socket către adresa loopback pe portul ''60001''. |
Porniți de la scheletul ''5-udp-sock/'' din scheletul laboratorului. | Porniți de la scheletul ''5-udp-sock/'' din scheletul laboratorului. | ||
Line 228: | Line 236: | ||
</note> | </note> | ||
- | Pentru testare folosiți scriptul ''test-5.sh'' și integrați executabilul static ''nc-static'' așa cum este descris în continuare. Scriptul este copiat pe mașina virtuală la ''make copy'' doar dacă este marcat ca executabil. | + | Pentru testare folosiți scriptul ''test-5.sh''. Scriptul este copiat pe mașina virtuală la ''make copy'' doar dacă este marcat ca executabil. Scriptul folosește utilitarul compilat static ''netcat'' din ''skels/networking/netcat''; acest executabil trebuie să aibă permisiuni de execuție. |
- | + | ||
- | <note important> | + | |
- | Utilitarul ''nc'' din busybox din mașina virtuală QEMU nu are suport pentru UDP. De aceea vom folosi un alt executabil. | + | |
- | + | ||
- | Pentru deschiderea unui socket UDP pe portul 60001 folosiți utilitarul netcat compilat static de la adresa http://www.stearns.org/nc/nc-static. Descărcați binarul pe sistemul fizic în directorul ''skels/networking/5-udp-sock/''. Binarul poate fi descărcat cu ajutorul comenzii<code> | + | |
- | wget http://www.stearns.org/nc/nc-static | + | |
- | </code> | + | |
- | + | ||
- | Verificați că fișierul a fost descărcat corect verificând suma de control MD5 cu ajutorul comenzii<code> | + | |
- | $ md5sum nc-static | + | |
- | ec6aa710d3112808cb31a1d6ded775a1 nc-static | + | |
- | </code> | + | |
- | + | ||
- | Înainte de pornirea mașinii virtuale QEMU, acordați executabilului ''nc-static'' permisiuni de execuție folosind<code> | + | |
- | chmod a+x nc-static | + | |
- | </code>, după care rulați comanda ''make copy'' pentru copierea pe mașina virtuală. | + | |
- | + | ||
- | După pornirea mașinii virtuale, copiați executabilul ''nc-static'' în ''/bin/nc'':<code> | + | |
- | cp nc-static /bin/nc | + | |
- | </code> | + | |
- | </note> | + | |
<note tip> | <note tip> | ||
Line 262: | Line 249: | ||
+ rmmod udp_sock | + rmmod udp_sock | ||
+ kill 1059 | + kill 1059 | ||
- | punt! | ||
</code> | </code> | ||
- | Mesajul ''punt!'' afișat în urma rulării testului ''test-5.sh'' este un mesaj afișat de utilitarul ''netcat'' în momentul în care procesul este oprit de rularea comenzii ''kill'' în cadrul scriptului. | ||
</note> | </note> | ||
Line 271: | Line 256: | ||
* [[http://elf.cs.pub.ro/so2/res/laboratoare/lab10-sol.zip|Soluții exerciții laborator 10]] | * [[http://elf.cs.pub.ro/so2/res/laboratoare/lab10-sol.zip|Soluții exerciții laborator 10]] | ||
- |