De citit înainte de laborator:
Lectura video
Lectura optionala
În urma parcurgerii acestui laborator, studentul va fi capabil să:
Programele se refera rareori la sisteme gazdă, cutii poștale și alte resurse prin adresele lor binare. În loc de numere binare, se utilizează șiruri ASCII, cum ar fi user@cs.pub.ro. Cu toate acestea, rețeaua înțelege numai adrese binare, deci este necesar un mecanism care să convertească șirurile ASCII în adrese de rețea. Protocolul care se ocupă de acest lucru se numește DNS (Domain Name System - sistemul numelor de domenii). Esența DNS-ului constă dintr-o schemă ierarhică de nume de domenii și dintr-un sistem de baze de date distribuite pentru implementarea acestei scheme de nume. Protocolul este definit in RFC-urile 1034 și 1035.
Primul mesaj e-mail a fost transmis in 1971 de un inginer pe nume Ray Tomlinson. Până la acea dată, puteau fi trimise mesaje doar în cadrul aceluiași calculator. Marea îmbunătățire introdusă de Tomlinson a fost posibilitatea de a trimite mesaje între calculatoare diferite din Internet, folosind semnul ’@’ pentru a desemna mașina spre care se trimite mesajul.
Azi se trimit miliarde de mesaje e-mail pe zi, si totuși multe din caracteristicile de atunci ale mesajelor au rămas.
DNS folosește în general protocolul UDP pe portul 53, dar, în cazul răspunsurilor de dimensiuni mai mari sau pentru operații ca transferul de zone, se utilizează și TCP. Mai recent, s-a introdus și DNS over HTTPS (sau DoH, descris în RFC 8484), care presupune realizarea de cereri DNS peste HTTPS din motive de securitate.
DNS organizează numele resurselor într-o ierarhie de domenii. Un domeniu reprezintă o colecție de sisteme gazdă care au unele proprietăți în comun, cum ar fi faptul că toate aparțin unei aceleiași organizații sau faptul că toate sunt situate geografic în același perimetru.
Fiecare domeniu este partiționat în subdomenii și acestea sunt la rândul lor, partiționate, ș.a.m.d. Toate aceste domenii pot fi reprezentate ca un arbore, după cum se poate vedea mai sus. Frunzele arborelui reprezintă domenii care nu au subdomenii, dar care conțin totuși sisteme. Un domeniu frunză poate conține de la un singur sistem gazdă până la mii de sisteme gazdă.
Domeniile de pe primul nivel se împart în două categorii: generice (gTLD-uri) și de țări (ccTLD-uri). Domeniile generice inițiale erau com (comercial), edu (instituții educaționale), gov (guvernul SUA), int (organizații internaționale), mil (forțele armate ale SUA) și org (organizații nonprofit). În ziua de astăzi, restricțiile legate de astfel de domenii sunt mult mai mici, existând astfel peste 1200 de domenii top-level generice. Domeniile de țări includ o intrare pentru fiecare țară, după cum se definește în ISO 3166. Fiecare domeniu este denumit de calea în arbore până la rădăcină. Componentele sunt separate prin punct. Astfel, departamentul de Calculatoare de la UPB poate fi cs.pub.ro în loc de numele în stil UNIX /ro/pub/cs.
Numele de domenii pot fi absolute sau relative. Un nume absolut de domeniu (FQDN - fully qualified domain name) este un nume de domeniu care nu permite nici o ambiguitate cu privire la locația relativă la rădăcina arborelui de nume de domenii. Astfel de nume absolute de domenii se termină cu punct (de exemplu cs.pub.ro.). În contrast, un nume relativ de domeniu este un nume care are sens numai relativ la un anume domeniu DNS (altul decât cel rădăcină).
Numele de domenii nu fac distincție între litere mici și litere mari, edu sau EDU însemnând practic același lucru. Componentele numelor pot avea o lungime de cel mult 64 de caractere, iar întreaga cale de nume nu trebuie să depășească 255 de caractere.
Fiecare domeniu controlează cum sunt alocate domeniile de sub el. De exemplu, Japonia are domeniile ac.jp și co.jp echivalente cu edu și com. Olanda nu face nicio distincție și pune toate organizațiile direct sub nl. Pentru a crea un nou domeniu, se cere permisiunea domeniului în care va fi inclus. De exemplu, dacă un grup PCom de la CS dorește să fie cunoscut ca pcom.cs.pub.ro, acesta are nevoie de permisiunea celui care administrează cs.pub.ro. Similar, o nouă universitate care dorește obținerea unui domeniu va trebui să ceară permisiunea administratorului domeniului edu. În acest mod, sunt evitate conflictele de nume și fiecare domeniu poate ține evidența tuturor subdomeniilor sale. Odată ce un nou domeniu a fost creat și înregistrat, el poate crea subdomenii, fără a cere permisiune de la cineva din partea superioară a arborelui.
Conceptele cu care DNS lucrează sunt:
Fiecărui domeniu, fie că este un singur calculator gazdă, fie un domeniu de nivel superior, îi poate fi asociată o mulțime de înregistrări de resurse (resource records sau RR-uri). Pentru un singur sistem gazdă, cea mai obișnuită înregistrare de resursă este chiar adresa IP, dar există multe alte tipuri.
Atunci când procedura resolver trimite un nume de domeniu DNS, ceea ce va primi ca răspuns sunt înregistrările de resurse asociate acelui nume. Astfel, adevărata funcție a DNS este să realizeze corespondența dintre numele de domenii și înregistrări de resurse.
O înregistrare de resursă este un 5-tuplu. Cu toate că, din rațiuni de eficiență, înregistrările de resurse sunt codificate binar, în majoritatea expunerilor ele sunt prezentate ca text ASCII, câte o înregistrare de resurse pe linie. Formatul utilizat este <Nume_domeniu, Timp_de_viață, Tip, Clasă, Valoare>:
Tip | Semnificație | Valoare |
---|---|---|
SOA | Start autoritate | Parametri pentru această zonă |
A | Adresa IPv4 a unui sistem gazdă | Întreg pe 32 de biți |
AAAA | Adresa IPv6 a unui sistem gazdă | Întreg pe 128 de biți |
MX | Schimb de poștă | Prioritate, domeniu dispus să accepte poștă electronică |
NS | Server de nume | Numele serverului pentru acest domeniu |
CNAME | Nume canonic | Numele domeniului |
PTR | Pointer | Pseudonim pentru adresă IP |
HINFO | Descriere sistem gazdă | Unitate centrală și sistem de operare în ASCII |
TXT | Text | Text ASCII neinterpretat |
O înregistrare SOA furnizează numele sursei primare de informație despre zona serverului de nume, adresa de e-mail a administratorului, un identificator unic si diverși indicatori și contoare de timp.
Cel mai important tip de înregistrare este înregistrarea A (adresă). Ea păstrează adresa IP de 32 de biți a sistemului gazdă. Următoarea ca importanță este înregistrarea MX. Aceasta precizează numele domeniului pregătit să accepte poștă electronică pentru domeniul specificat. Înregistrările specifică numele serverului. Un exemplu de informație ce se poate găsi în baza de date DNS a unui domeniu este următorul:
; Authoritative Information on physics.groucho.edu. @ IN SOA niels.physics.groucho.edu. janet.niels.physics.groucho.edu. { 1999090200 ; serial no 360000 ; refresh 3600 ; retry 3600000 ; expire 3600 ; default ttl }; ; Name servers IN NS niels IN NS gauss.maths.groucho.edu. gauss.maths.groucho.edu. IN A 149.76.4.23 ; ; Theoretical Physics (subnet 12) niels IN A 149.76.12.1 IN A 149.76.1.12 name server IN CNAME niels otto IN A 149.76.12.2 quark IN A 149.76.12.4 down IN A 149.76.12.5 strange IN A 149.76.12.6 ... ; Collider Lab. (subnet 14) boson IN A 149.76.14.1 muon IN A 149.76.14.7 bogon IN A 149.76.14.12 ...
Teoretic, un singur server de nume poate conține întreaga bază de date DNS și poate să răspundă tuturor cererilor. În practică, acest server poate fi atât de încărcat încât să devina de neutilizat. Pentru a evita probleme asociate cu existența unei singure surse de informație, spațiul de nume DNS este împărțit în zone care nu se suprapun. O posibilă astfel de împărțire este cea de mai jos.
Fiecare astfel de zonă conține câte o parte a arborelui, precum și numele serverelor care păstrează informația autorizată despre acea zonă. În mod normal, o zonă va avea un server de nume primar, care preia informația dintr-un fișier de pe discul propriu, și unul sau mai multe servere de nume secundare, care iau informația de la serverul primar. Pentru a îmbunătăți fiabilitatea, unele servere pentru o zonă pot fi plasate chiar în afara zonei.
Plasarea limitelor unei zone este la latitudinea administratorului ei. Această decizie este luată în mare parte pe baza numărului de servere de nume care se doresc a se folosi, și a locației acestora. Atunci când un resolver are o cerere referitoare la un nume de domeniu, el transferă cererea unuia din serverele locale de nume. Dacă domeniul este sub jurisdicția serverului de nume, el va întoarce înregistrări de resurse autorizate. O înregistrare autorizata (authoritative record) este cea care vine de la autoritatea care administrează înregistrarea, și astfel este întotdeauna corectă. Înregistrările autorizate se deosebesc de înregistrările din memoria cache, care pot fi expirate.
Dacă totuși domeniul se află la distanță, iar local nu este disponibilă nici o informație despre el, atunci serverul de nume trimite un mesaj de cerere către serverul de nume de pe primul nivel al domeniului solicitat. De menționat că metoda de interogare este recursivă (recursive query), deoarece fiecare server care nu are informația cerută o caută în altă parte și raportează.
Până de curând, pentru a afla un nume pe baza unei adrese IP și o adresă pe baza unui nume, se foloseau funcțiile gethostbyname() și gethostbyaddr(), împreună cu structura hostent. Între timp, acest API pentru DNS a fost scos din uz.
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h> int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
Funcția getaddrinfo() primește informații despre numele unei gazde și al unui serviciu Internet, și returnează adresa sau adresele corespunzătoare. Parametrul node reprezintă numele simbolic (sub forma unui șir de caractere) al mașinii căreia vrem sa-i aflăm adresa (de exemplu, node poate fi “www.google.com”). Mai poate de asemenea fi reprezentat ca un șir care conține o adresă IPv4 sau IPv6.
Parametrul service specifică portul returnat în output, și poate fi pus pe NULL (caz în care portul din output rămâne neinițializat) sau poate fi dat ca un nume de serviciu (de exemplu, “http”) sau ca o valoare numerică (“80”).
Parametrul hints reprezintă criterii pentru filtrarea adreselor întoarse de apelul funcției getaddrinfo(). Este de tipul struct addrinfo, definit mai jos:
struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; socklen_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; };
În cazul în care se dorește filtrarea, se pot completa unul sau mai multe din următoarele câmpuri (restul punându-se pe 0):
În final, rezultatul este pus în parametrul res, fiind reprezentat ca o listă înlănțuită de structuri de tipul addrinfo, care se parcurge prin intermediul câmpului ai_next. Din câmpul ai_addr al rezultatului, se pot citi informațiile despre adresa și portul stației gazdă căutate (prin cast la struct sockaddr_in, de exemplu).
În caz de succes, funcția întoarce 0, iar în caz de eroare întoarce o valoare negativă, care poate fi interpretată prin intermediul funcției gai_strerror():
const char *gai_strerror(int errcode);
void freeaddrinfo(struct addrinfo *res);
Pentru a afișa adresa IP (v4 sau v6) corespunzătoare numelui simbolic din parametrul node, se poate utiliza funcția inet_ntop():
#include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
Primul parametrul specifică familia de protocoale (AF_INET sau AF_INET6), al doilea parametru reprezintă structura de adresă (adică, de exemplu, câmpurile sin_addr sau sin6_addr din structurile sockaddr_in pentru IPv4 sau sockaddr_in6 pentru IPv6), al treilea parametru reprezintă un șir de caractere unde va fi scrisă adresa sub formă de string, iar ultimul parametru reprezintă dimensiunea șirului de caractere în octeți. Valoarea de retur a funcției este un pointer la un șir de caractere identic cu cel din parametrul dst, sau NULL în caz de eroare.
#include <sys/socket.h> #include <netdb.h> int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags);
Funcția getnameinfo() realizează operația inversă față de getaddrinfo(). Mai precis, primește o adresă și returnează numele simbolic și serviciul specifice adresei respective. Primii doi parametri reprezintă adresa IP (v4 sau v6) care este căutată. Se trimit structuri specifice protocolului dorit (sockaddr_in sau sockaddr_in6) și dimensiunea lor. Rezultatele apelului sunt puse în șirurile de caractere host și serv, care sunt alocate de către utilizator. Parametrii hostlen și servlen reprezintă dimensiunile celor două șiruri de caractere.
Funcția returnează 0 dacă s-a reușit cererea DNS, sau o valoare negativă interpretată cu gai_strerror() în caz contrar.
În Linux, pentru a obține adresele IP ale unei gazde, putem folosi unul din utilitarele host sau nslookup:
$ host google.com google.com has address 172.217.20.14 google.com has IPv6 address 2a00:1450:400d:804::200e google.com mail is handled by 30 alt2.aspmx.l.google.com. google.com mail is handled by 50 alt4.aspmx.l.google.com. google.com mail is handled by 20 alt1.aspmx.l.google.com. google.com mail is handled by 10 aspmx.l.google.com. google.com mail is handled by 40 alt3.aspmx.l.google.com.
$ nslookup google.com Server: 192.168.100.1 Address: 192.168.100.1#53 Non-authoritative answer: Name: google.com Address: 172.217.20.14
Pentru aflarea unui nume pe baza unei adrese IP, se pot folosi tot host sau nslookup:
$ host 8.8.8.8 8.8.8.8.in-addr.arpa domain name pointer dns.google.
$ nslookup 8.8.8.8 8.8.8.8.in-addr.arpa name = dns.google. Authoritative answers can be found from: in-addr.arpa nameserver = a.in-addr-servers.arpa. in-addr.arpa nameserver = b.in-addr-servers.arpa. in-addr.arpa nameserver = c.in-addr-servers.arpa. in-addr.arpa nameserver = e.in-addr-servers.arpa. in-addr.arpa nameserver = d.in-addr-servers.arpa. in-addr.arpa nameserver = f.in-addr-servers.arpa.
Un exemplu de output tcpdump pentru comanda host este mai jos (unde 53 este portul implicit pentru DNS):
$ sudo tcpdump port 53 tcpdump: data link type PKTAP tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes 08:12:17.446368 IP 192.168.100.4.63991 > 192.168.100.1.domain: 31461+ A? google.com. (28) 08:12:17.450412 IP 192.168.100.1.domain > 192.168.100.4.63991: 31461 1/0/0 A 172.217.16.110 (44) 08:12:18.455598 IP 192.168.100.4.58146 > 192.168.100.1.domain: 4039+ AAAA? google.com. (28) 08:12:18.463761 IP 192.168.100.1.domain > 192.168.100.4.58146: 4039 1/0/0 AAAA 2a00:1450:400d:803::200e (56) 08:12:19.467330 IP 192.168.100.4.53016 > 192.168.100.1.domain: 58519+ MX? google.com. (28) 08:12:19.514778 IP 192.168.100.1.domain > 192.168.100.4.53016: 58519 5/0/0 MX alt3.aspmx.l.google.com. 40, MX alt4.aspmx.l.google.com. 50, MX aspmx.l.google.com. 10, MX alt1.aspmx.l.google.com. 20, MX alt2.aspmx.l.google.com. 30 (136)
dig (Domain Information Groper) este un utilitar Linux care interoghează servere de nume și afișează rezultatele într-o varietate de forme.
Înainte a vedea cum funcționează dig, este util să observăm formatul unui pachet DNS, prezentat mai jos (formatul fiecărei secțiuni se găsește detaliat în RFC 1035):
+---------------------+ | Antet | +---------------------+ | Întrebare | întrebarea pentru serverul de nume +---------------------+ | Răspuns | RR-uri care răspund la întrebare +---------------------+ | Autoritate | RR-uri care indică o autoritate +---------------------+ | Adițional | RR-uri care conțin informație adițională +---------------------+
Pentru a interoga o singură gazdă, comanda de dig arată în felul următor:
$ dig google.com
Output-ul obținut se mapează pe structura unui răspuns standard DNS, cu mențiunea că unele din RR-uri (de exemplu, cele adiționale sau de autoritate) pot să lipsească. Prima parte a output-ului conține informații despre versiunea de dig folosită și opțiunile alese:
; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> google.com ;; global options: +cmd
Mai departe, urmează desfășurarea răspunsului primit de la server-ul DNS, începând cu antetul:
;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35678 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 1
În continuare, se afișează partea de întrebare (în exemplul nostru, pentru o adresă IPv4, adică A):
;; QUESTION SECTION: ;google.com. IN A
După întrebare, urmează RR-urile de răspuns (în cazul nostru, este unul singur, adică adresa IP a gazdei date):
;; ANSWER SECTION: google.com. 300 IN A 172.217.16.142
Mai departe, secțiunea cu RR-uri de autoritate ne spune ce servere DNS pot să ne ofere răspunsuri autoritare la cererile noastre:
;; AUTHORITY SECTION: . 214056 IN NS c.root-servers.net. . 214056 IN NS b.root-servers.net. . 214056 IN NS a.root-servers.net. . 214056 IN NS d.root-servers.net.
În continuare, ar putea urma secțiunea de RR-uri adiționale (care ar putea include, de exemplu, adresele serverelor de nume autoritare din secțiunea precedentă), iar la final ni se oferă statistici despre cerere:
;; Query time: 37 msec ;; SERVER: 172.16.10.254#53(172.16.10.254) ;; WHEN: Thu Apr 09 07:32:54 EEST 2020 ;; MSG SIZE rcvd: 266
Așa cum se poate observa și mai sus, o cerere implicită de dig este realizată cu tipul A (adresă IPv4). Dacă se doresc altfel de cereri, acest lucru se poate specifica la rulare, imediat după numele gazdei. Pe lângă înregistrările propriu-zise, putem folosi și wildcard-ul ANY, care ne interoghează după toate tipurile de RR-uri:
$ dig ANY google.com [...] ;; ANSWER SECTION: google.com. 283 IN AAAA 2a00:1450:400d:805::200e google.com. 39 IN SOA ns1.google.com. dns-admin.google.com. 305440781 900 900 1800 60 google.com. 25 IN A 172.217.20.14 google.com. 26083 IN NS ns3.google.com. [...]
Dacă nu ne interesează tot output-ul de mai sus și vrem să afișăm doar adresa IP (v4 sau v6), putem folosi opțiunea +short:
$ dig A google.com +short 172.217.20.14 $ dig AAAA google.com +short 2a00:1450:400d:803::200e
Dacă dorim să nu afișăm vreuna din secțiunile de răspuns ale dig, putem alege din opțiunile de mai jos:
Dacă dorim, putem dezactiva afișarea tuturor secțiunilor (cu opțiunea +noall) și apoi să alegem ce vrem să afișăm. Astfel, cele două comenzi de mai jos sunt echivalente, afișând doar secțiunea de răspuns:
$ dig google.com +nocomments +noquestion +noauthority +noadditional +nostats ; <<>> DiG 9.10.6 <<>> google.com +nocomments +noquestion +noauthority +noadditional +nostats ;; global options: +cmd google.com. 56 IN A 216.58.214.238 $ dig google.com +noall +answer ; <<>> DiG 9.10.6 <<>> google.com +noall +answer ;; global options: +cmd google.com. 43 IN A 216.58.214.23
În mod implicit, dig folosește serverele de nume din fișierul /etc/resolv.conf. Totuși, dacă dorim, putem specifica serverul de nume pe care îl interogăm în felul următor:
$ dig @8.8.8.8 google.com [...] $ dig @ns1.google.com google.com [...]
Dacă se dorește interogarea unui server DNS pentru un număr mai mare de gazde (o interogare de tip bulk), acest lucru se poate face prin adăugarea lor într-un fișier și folosirea opțiunii -f:
$ cat queries.txt google.com facebook.com twitter.com $ dig -f queries.txt +noall +answer google.com. 106 IN A 172.217.19.110 facebook.com. 43 IN A 185.60.218.35 twitter.com. 1052 IN A 104.244.42.193 twitter.com. 1052 IN A 104.244.42.1
Așa cum s-a menționat și mai sus, sistemul DNS este organizat ierarhic, deci o cerere dig parcurge mai multe servere DNS. Acest lucru se poate observa prin intermediul parametrului +trace:
$ dig google.com +noall +answer +trace
Pentru a realiza o căutare inversă (reverse lookup), se folosește opțiunea -x pentru a obține domeniul și numele asociate cu un IP:
$ dig -x 8.8.8.8 +noall +answer ; <<>> DiG 9.10.6 <<>> -x 8.8.8.8 +noall +answer ;; global options: +cmd 8.8.8.8.in-addr.arpa. 17648 IN PTR dns.google.
Un mesaj e-mail a fost întotdeauna transmis în format plain-text (text clar). Chiar si prin adăugarea atașamentelor, mesajele de e-mail sunt trimise tot ca mesaje plain-text, prin folosirea unor mecanisme de codificare (uuencode/uudecode, MIME/BASE64).
Un mesaj este format dintr-o secțiune de antete (headers), urmată de o secțiune cu conținutul mesajului. Structura antetelor este descrisă în RFC 822, RFC 1521 și RFC 1806, ele având în general următoarea structură:
Conținutul mesajului este textul propriu-zis, pentru mesajele în text clar fără atașamente. Se poate observa mai jos un exemplu de mesaj:
MIME-Version: 1.0 From: profesor@upb.ro To: student@upb.ro Subject: Tema Content-Type: text/plain Draga student, Fa-ti tema! Cu bine, Profesorul.
Mesajele cu atașamente pot folosi una din următoarele tehnici pentru codificarea acestora:
Un mesaj cu atașamente codificate MIME arată în felul următor:
MIME-Version: 1.0 From: Student Studentescu <student@upb.ro> To: Profesor PC <profesor@upb.ro> Subject: Re: Tema Content-Type: multipart/mixed; boundary=abc --abc Content-Type: text/plain Atasez tema. Cu bine, Studentul --abc Content-Type: text/plain Content-Disposition: attachment; filename="tema.c" #include <stdio.h> int main() { printf("Aceasta este tema mea\n"); return 0; } --abc
Se observă faptul că părțile care compun mesajul sunt separate între ele printr-un șir de caractere separator (boundary string), specificat ca un parametru pentru antetul Content-Type. Fiecare parte poate avea la rândul ei propriile antete, care conțin în general tipul și numele fișierului din secțiunea respectivă. În cazul în care se trimit atașamente binare, acestea sunt codificate folosind schema numită Base64, descrisă în RFC 1521.
În terminologia folosită de sistemele de e-mail, există trei actori. Aceștia pot fi situați pe trei mașini diferite sau pot co-exista pe aceeași gazdă:
SMTP (Simple Mail Transfer Protocol) este un protocol care se folosește pentru trimiterea mesajelor electronice (de la un client către un server). Acesta se foloseste de portul 25 peste TCP și este descris în RFC 821 și RFC 5321.
Mesajele necesare în SMTP pentru trimiterea unui e-mail sunt următoarele:
1: HELO client.upb.ro 2: MAIL FROM: <profesor@upb.ro> 3: RCPT TO: <student@upb.ro> 4: DATA 5: MIME-Version: 1.0 From: profesor@upb.ro To: student@upb.ro Subject: Tema Content-Type: text/plain Draga student, Fa-ti tema! Cu bine, Profesorul. . 6: QUIT
Se trimite deci întâi o comandă “HELO” cu numele de domeniu sau adresa IP a clientului pentru a iniția sesiunea, apoi o comandă “MAIL FROM” cu adresa sursei, “RCPT TO” pentru destinație, “DATA” pentru date (e-mail-ul în sine) și “QUIT” pentru a se închide sesiunea. Secțiunea de date trebuie neapărat terminată cu secvența de caractere <CR><LF>.<CR><LF>
(adică o linie nouă urmată de un punct și apoi de încă o linie nouă).
Găsiți mai jos modul implmentare in C a unui mesaj SMTP.
POP3 (Post Office Protocol 3) este un protocol utilizat pentru citirea mesajelor electronice (de la un server către un client). Clientul va interoga periodic serverul, va descărca mesajele și le va șterge automat de pe server. Comunicația se realizează folosind portul 110 peste TCP, în felul următor:
1: USERNAME username 2: PASS password 3: LIST 4: RETR 1 5: QUIT
IMAP (Internet Message Access Protocol) este un protocol care se folosește pentru citirea mesajelor electronice (de la un server catre un client). Clientul interoghează periodic serverul și poate cere mesaje complete sau doar porțiuni (header, body), și nu va șterge automat mesajele de pe server. Comunicația se realizează prin TCP, folosind portul 143.
1: LOGIN username password 2: LIST "" "*" 3: EXAMINE Inbox 4: FETCH 1 BODY[] 5: LOGOUT
Va oferim aici un cod sursă schelet pentru realizarea unei aplicații in C care utilizează API-ul DNS.
Va oferim aici un cod sursă schelet pentru realizarea unui client de email SMTP scris in C. Veți folosi un server SMTP acre rulează local. Acesta poate fi creat folosind un utilitar existent în Python, numit smtpd. Rularea acestui utiliar pe portul 25 se face astfel:
sudo python -m smtpd -n -c DebuggingServer 127.0.0.1:25
Pornind de la codul disponibil aici, implementați următoatrea cerință:
1. Scrieți un program care să afișeze numele și adresele IP pentru un host. Programul poate primi ca parametru fie numele (caz în care se va afișa adresa), fie adresa IP (caz în care se va afișa numele). Testați-va programul folosind informațiile din tabelul de mai jos. Exemplu de apel:
./dns -n google.com ./dns -a 8.8.8.8
2. Folosind utilitarul dig, realizați următoarele sarcini:
Găsiți mai jos un tabel cu o serie de gazde și RR-urile asociate:
Pornind de la codul disponibil aici, implementați următoatrea cerință:
1. Implementați un client SMTP peste TCP prin care să trimiteți către serverul smtpd un e-mail care conține niște text și un fișier dat ca parametru sub forma unui atașament de tip text/plain (API-ul necesar pentru conexiunea TCP cu server-ul este detaliat în laboratorul 7).