Presentazione del corso - Università degli Studi di Milano
Transcript
Risoluzione Nomi e Indirizzi in C Corso di laurea in Informatica Laboratorio di Reti di Calcolatori A.A. 2014-2015 Simone Bassis [email protected] Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI Una nota sugli OS o Assumiamo di lavorare su Linux, BSD o altri sistemi Unix o Usando come compilatore GNU gcc o Per piattaforme o Solaris/SunOS • È necessario aggiungere alcune direttive in fase di compilazione – -lnsl –lsocket –lresolv – -lxnet o Windows • • • • Dopo diversi anni… sentitevi liberi di usare windows, ma… Valutate se installare Cygwin (collezione di tool Unix per Windows) O crearvi una partizione Linux Oppure usate le librerie WinSocks Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 363 1 Una nota su Windows #include <winsock.h> { WSADATA wsaData; // se non dovesse funzionare // MAKEWORD(1,1) for Winsock 1.1, // MAKEWORD(2,0) for Winsock 2.0: if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) { fprintf(stderr, "WSAStartup failed.\n"); exit(1); } Linkando le librerie Winsock o o wsock32.lib, winsock32.lib o ws2_32.lib Ripulendo il sistema al termine o o WSACleanup() Facendo attenzione ad alcune differenze o o o o o Closesocket() select() su socket descriptor Presenza della classe Csocket CreateProcess() e CreateThread() Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 364 POSIX o o POSIX (Portable Operating System Interface for Unix) indica la famiglia degli standard definiti dall’IEEE denominati formalmente IEEE 1003. Il nome standard internazionale è ISO/IEC 9945. Gli standard POSIX derivano da un progetto, iniziato circa nel 1985, finalizzato alla standardizzazione o delle API per i software sviluppati per le diverse varianti dei sistemi operativi UNIX o dei comandi di shell e utility interfaces per software compatibili su diverse piattaforme Unix e anche diversi sistemi operativi o Posix per Windows o Cygwin: POSIX-compliant development and run-time environment o Microsoft POSIX subsystem, un sottosistema Windows opzionale (no threads, no sockets) o Microsoft Windows Services for UNIX (full POSIX compliance) • È built in nelle versioni Enterprise e Ultimate di Windows 7 o UWIN dalla AT&T Research implementa un layer POSIX sopra le APIs Win32 o MKS Toolkit Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 365 2 Socket in C o Un modo per dialogare con altri programmi usando Unix file descriptor o Un programma Unix fa I/O avvalendosi di un file descriptor o Un intero associato ad un file aperto • • • • • • • Connessione di rete FIFO Pipe Terminale Un file vero e proprio … Tutto in Unix è un file! Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 366 Socket in C o o È sufficiente ottenere un socket descriptor tramite socket() E invocare send() e recv() o Si possono usare anche read() e write() ma offrono meno controlli o Quali Socket? o Non solo… • Internet Socket • Unix Socket • X.25 Socket o Ma molti altri • In funzione della piattaforma Unix Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 367 3 /* Address families. */ #define AF_UNSPEC #define AF_LOCAL #define AF_UNIX #define AF_FILE #define AF_INET #define AF_AX25 #define AF_IPX #define AF_APPLETALK #define AF_NETROM #define AF_BRIDGE #define AF_ATMPVC #define AF_X25 #define AF_INET6 #define AF_ROSE #define AF_DECnet #define AF_NETBEUI #define AF_SECURITY #define AF_KEY #define AF_NETLINK #define AF_ROUTE #define AF_PACKET #define AF_ASH #define AF_ECONET #define AF_ATMSVC #define AF_SNA #define AF_IRDA #define AF_PPPOX #define AF_WANPIPE #define AF_BLUETOOTH #define AF_MAX Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 22 23 24 25 31 32 /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* Unspecified. */ Local to host (pipes and file-domain). */ Old BSD name for AF_LOCAL. */ Another non-standard name for AF_LOCAL. */ IP protocol family. */ Amateur Radio AX.25. */ Novell Internet Protocol. */ Appletalk DDP. */ Amateur radio NetROM. */ Multiprotocol bridge. */ ATM PVCs. */ Reserved for X.25 project. */ IP version 6. */ Amateur Radio X.25 PLP. */ Reserved for DECnet project. */ Reserved for 802.2LLC project. */ Security callback pseudo AF. */ AF_KEY key management API. */ /* /* /* /* /* /* /* /* /* /* /* Alias to emulate 4.4BSD. */ Packet family. */ Ash. */ Acorn Econet. */ ATM SVCs. */ Linux SNA Project */ IRDA sockets. */ PPPoX sockets. */ Wanpipe API sockets. */ Bluetooth sockets. */ For now.. */ S. Bassis ([email protected]) Università di Milano – DI 368 Tre Tipologie di Socket o SOCK_STREAM: Stream Socket o Connessione affidabile a due vie o Che fa uso del protocollo TCP o SOCK_DGRAM: Datagram Socket o Connectionless o Che fa uso del protocollo UDP o SOCK_RAW: Raw Socket o Accesso diretto alla rete • o “Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers.” In realtà su alcune piattaforme anche o o o o SOCK_RDM (Reliable Datagram Message) SOCK_SEQPACKET (Reliable Sequenced Packet Service) SOCK_DCCP (Datagram Congestion Control Protocol) SOCK_PACKET (Datalink Access) Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 369 4 Byte-Order o Se voglio memorizzare/inviare il numero esadecimale b34f uso i due byte o b3 seguito da 4f (Big Endian) o 4f seguito da b3 (Little Endian) • Piattaforme Intel o compatibili o Big Endian • sembra più sensato • È anche definito Network Byte Order • Da non confondersi con Host Byte Order – Dipende ovviamente dalla piattaforma Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 370 Byte-Order o Sulla rete i dati viaggiano sempre in Network Byte Order o È sufficiente assumere che l’Host Byte Order non sia corretto o E usare funzioni che effettuano le opportune conversioni • Così da rendere portabile il proprio codice o Due tipi di dati possono essere convertiti o long (4 byte) o short (2 byte) o Tramite o o o o htons() htonl() ntohs() ntohl() host to network host to network network to host network to host Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI short long short long 371 5 Alcuni tipi di dati socket descriptor int addrinfo: rappresenta indirizzi e hostname 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; }; /* /* /* /* /* /* /* /* AI_PASSIVE, AI_CANONNAME, etc. */ AF_INET, AF_INET6, AF_UNSPEC */ SOCK_STREAM, SOCK_DGRAM */ use 0 for ‘any’ */ size of ai_addr in byte; tipo size_t su OS meno recenti*/ struct sockadder_in or _in6 */ full canonical hostname */ this struct can form a linked list, next node */ • • Si riempie tramite getaddrinfo() Si può forzare IPv4, IPv6 o lasciarlo non specificato • • Si possono ottenere diversi risultati tra cui scegliere (è una linked list) Struct sockaddr è la parte più importante • Per una versione agnostica del codice • contiene informazioni sull’indirizzo per una ampia famiglia di socket getaddrinfo() fa il grosso del lavoro • Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 372 Alcuni tipi di dati sockaddr: conetiene informazioni su socket address per vari tipi di socket struct sockaddr { unsigned short sa_family; char sa_data[14]; }; • • // address family, AF_xxx // 14 bytes of protocol address È un contenitore generico di indirizzi Per fortuna esistono strutture parallele che si possono castare vicendevolmente sockaddr per indirizzi IPv4 struct sockaddr_in { short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; • // // // // Address family, AF_INET Port number (in Network Byte Order) Internet address Same size as struct sockaddr i byte in sin_zero devono essere settati a zero con memset() struct sockaddr_in foo; memset(&foo, 0, sizeof foo); • e compare un nuovo internet address in_addr… Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 373 6 Alcuni tipi di dati Internet address: una struct per motivi storici struct sin_addr { uint32_t s_addr; }; • • // a 32-bit int (4 bytes) se ina è una struct sockaddr_in, allora ina.sin_addr.s_addr è un riferimento all’indirizzo IP all’epoca era una union, ma grazie a #define non cambia nulla Ma anche: sockaddr per indirizzi IPv6 struct sockaddr_in6 { u_int16_t sin6_family; u_int16_t sin6_port; u_int32_t sin6_flowinfo; struct in6_addr sin6_addr; u_int32_t sin6_scope_id; struct sin6_addr { unsigned char s6_addr[16]; }; // // // // // address family, AF_INET6 port number, Network Byte Order IPv6 traffic class and flow information IPv6 address Set of interfaces for a scope // IPv6 address Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 374 Alcuni tipi di dati o sockaddr generiche sia per IPv4 che per IPv6 struct sockaddr_storage { sa_family_t ss_family; // address family // ciò che segue è un padding dipendente dall’implementezione… potete ignorarlo // è definite in questo modo per questioni legate all’allineamento della struct char __ss_pad1[_SS_PAD1SIZE]; int64_t __ss_align; char __ss_pad2[_SS_PAD2SIZE]; }; • • Usato quando non si sa se l’indirizzo che si riceverà è IPv4 o IPv6 In funzione di sa_family (AF_INET or AF_INET6) castate nello struct sockaddr opportuno oppure: sockaddr per Unix domain socket: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; } Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI /* AF_UNIX */ 375 7 Manipolare indirizzi IP o o Per fortuna, ci sono diverse funzioni che ci vengono in aiuto inet_pton() o converte un indirizzo IP espresso in dot notation (o hex and colons) in uno struct in_addr o struct in6_addr in funzione della famiglia specificata (AF_INET o AF_INET6). o “pton” sta per “presentation to network” o In passato inet_addr() o inet_aton() ma non funzionano con IPv6 struct sockaddr_in sa; // IPv4 struct sockaddr_in6 sa6; // IPv6 inet_pton(AF_INET, "192.0.2.1", &(sa.sin_addr)); inet_pton(AF_INET6, "2001:db8:63b3:1::3490", &(sa6.sin6_addr)); o // IPv4 //IPv6 Attenzione al valore di ritorno o 1: successo o 0: l’indirizzo sorgente non è valido nella famiglia specificata o -1: se la famiglia specificata non è supportata; errno è settato a EAFNOSUPPORT Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 376 Manipolare indirizzi IP o inet_ntop() o Come prima, ma al contrario o macro INET_ADDRSTRLEN e INET6_ADDRSTRLEN definiscono la lunghezza di un indirizzo IPv4 e IPv6 o Ricordatevi di controllare il valore di ritorno • • Guardatevi il manuale per gestire correttamente tutte le casistiche Sulle slide non sempre verranno gestiti opportunamente i codici di ritorno // IPv4: char ip4[INET_ADDRSTRLEN]; // buffer per la stringa IPv4 struct sockaddr_in sa; // supponiamo contenga un indirizzo valido inet_ntop(AF_INET, &(sa.sin_addr), ip4, INET_ADDRSTRLEN); printf("The IPv4 address is: %s\n", ip4); // IPv6: char ip6[INET6_ADDRSTRLEN]; // buffer per la stringa IPv6 struct sockaddr_in6 sa6; // supponiamo contenga un indirizzo valido inet_ntop(AF_INET6, &(sa6.sin6_addr), ip6, INET6_ADDRSTRLEN); printf("The address is: %s\n", ip6); o La funzione inet_ntoa() è deprecata o In entrambi i casi non viene effettuata una risoluzione tramite DNS Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 377 8 // Helper function: // Converte un indirizzo struct sockaddr address in una string, // IPv4 and IPv6: Nota: helper function come quella a fianco sono essenziali per sviluppare codice portabile e funzionante su diversi sistemi di indirizzamento char *get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) { switch(sa->sa_family) { case AF_INET: inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen); break; case AF_INET6: inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen); break; default: strncpy(s, "Unknown AF", maxlen); return NULL; // IPv4 demo di inet_ntop() e inet_pton() } struct sockaddr_in sa; return s; char str[INET_ADDRSTRLEN]; } Manipolare indirizzi IP // si memorizza l’indirizzo IP in sa inet_pton(AF_INET, "192.0.2.33", &(sa.sin_addr)); // si riottiene inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN); printf("%s\n", str); // stampa "192.0.2.33" // IPv6 demo di inet_ntop() e inet_pton() struct sockaddr_in6 sa; char str[INET6_ADDRSTRLEN]; // si memorizza l’indirizzo IP in sa inet_pton(AF_INET6, "2001:db8:8714:3a90::12", &(sa.sin6_addr)); // si riottiene inet_ntop(AF_INET6, &(sa.sin6_addr), str, INET6_ADDRSTRLEN); Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 378 printf("%s\n", str); // stampa "2001:db8:8714:3a90::12" S. Bassis ([email protected]) Università di Milano – DI System Call getaddrinfo() o o Chiamando queste funzioni, è il kernel a prendere il controllo dell’esecuzione Attenzione all’error checking e a controlli sulle entry restituite da getaddrinfo() o getaddrinfo(): serve per effettuare DNS lookup e service name lookup #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); o o o // es. "www.example.com" o indirizzo IP // es. "http" o port number node: hostname o indirizzo IP service: port number o service name hints: struct addrinfo inizializzata con informazioni rilevanti Nota: in passato gethostbyname() o getservbyname() o o Bisognava caricare il risultato in uno struct sockaddr_in Non funziona con IPv6 Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 379 9 System Call getaddrinfo() Server side int status; struct addrinfo hints; struct addrinfo *servinfo; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // punterà ai risultati // per assicurarsi che lo struct sia vuoto // accetta sia IPv4 che IPv6 // TCP stream socket if ((status = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); exit(1); } // ora servinfo punta ad una linked list di 1 o più struct addrinfo // ... si eseguono tutte le istruzioni del caso finchè non servirà più servinfo freeaddrinfo(servinfo); o // un po’ di pulizia sulla linked-list Flags: ce ne sono diversi, ma AI_PASSIVE è il più rilevante o Se AI_PASSIVE è specificato e node è NULL, allora l’indirizzo restituito potrà essere associato ad una socket che accetta connessioni. • • o Conterrà il "wildcard address" (INADDR_ANY per IPv4, IN6ADDR_ANY_INIT per IPv6). Questo sarà seguito da una chiamata a bind() che inserirà nello struct sockaddr l’indirizzo dell’host corrente Se AI_PASSIVE non è specificato, allora l’indirizzo restituito potrà essere associato ad una socket per connettersi o inviare messaggi • Se node è NULL, l’indirizzo di rete è settato all’indirizzo dell’interfaccia di loopback (INADDR_LOOPBACK per IPv4, IN6ADDR_LOOPBACK_INIT per IPv6) Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 380 System Call getaddrinfo() Client side int status; struct addrinfo hints; struct addrinfo *servinfo; // punterà ai risultati memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; // per assicurarsi che lo struct sia vuoto // accetta sia IPv4 che IPv6 // TCP stream socket // pronto per la connessione status = getaddrinfo("www.example.net", "3490", &hints, &servinfo); // ora servinfo punta ad una linked list di 1 o più struct addrinfo // etc. etc. o o AF_UNSPEC può essere sostituito da AF_INET o AF_INET6 gai_strerror() stampa l’errore nel caso in cui il valore di ritorno sia diverso da 0 Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 381 10 showip.c /* showip.c – mostra gli indirizzi IP di un host passato da linea di comando */ if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { #include <stdio.h> fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); #include <string.h> return 2; #include <sys/types.h> } #include <sys/socket.h> #include <netdb.h> #include <arpa/inet.h> printf("IP addresses for %s:\n\n", argv[1]); int main(int argc, char *argv[]) { struct addrinfo hints, *res, *p; int status; char ipstr[INET6_ADDRSTRLEN]; for(p = res;p != NULL; p = p->ai_next) { void *addr; char *ipver; // si ottiene il puntatore all’indirizzo stesso, // facendo attenzione ai diversi campi in IPv4 e IPv6: if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = "IPv4"; } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = "IPv6"; } if (argc != 2) { fprintf(stderr,"usage: showip hostname\n"); return 1; } memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; Stampa l’indirizzo IP degli host specificati a linea di comando // si converte l’indirizzo IP e si stampa $ showip www.example.net inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf(" %s: %s\n", ipver, ipstr); } IP addresses for www.example.net: IPv4: 192.0.2.88 $ showip ipv6.example.com IP addresses for ipv6.example.com: IPv4: 192.0.2.101 IPv6: 2001:db8:8c00:22::171 Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI } freeaddrinfo(res); return 0; // un po’ di pulizia 382 Esercizio C1 Scrivere un programma il più possibile simile al programma nslookup, disponibile sia in ambiente unix che windows, cercando di implementarne le sole caratteristiche di base: • • • Conversione multipla da nomi a indirizzi Conversione nei due sensi IP -> nome e viceversa Modalità come parametro – • Il valore da convertire è passato come parametro al programma esempio: NSLookUP www.unimi.it Modalità in linea – Il programma presenta un prompt e poi tenta di convertire tutto ciò che viene digitato Suggerimento: può essere opportuno usare tanto la funzione getaddrinfo() quanto getnameinfo() Laboratorio di Reti di Calcolatori (Informatica) - A.A. 2014-2015 S. Bassis ([email protected]) Università di Milano – DI 383 11
Documenti analoghi
Basic Sniffer Tutorial
unsigned char tos; //Tipo del servizio unsigned short t_len; //Lunghezza totale unsigned short ident; //IP Ident unsigned short frag_and_flags; //Frammenti e Flags unsigned char ttl; //Time To Live...
Dettaglinon bloccante - Università degli Studi di Milano
Buona norma avere un protocollo che preveda come prefisso la dim. attuale del messaggio private ByteBuffer packMessage(String text) { ByteBuffer data = (ByteBuffer)Charset.forName("UTF-8").encode(t...
DettagliPresentazione del corso - Università degli Studi di Milano
fruire del servizio, però possono essere utili per
DettagliIPv6 transition - the Netgroup at Politecnico di Torino
Far more than 50% of the code related to the socket interface must be changed. And, for the rest, who knows?
DettagliNR #12 - OoCities
VB. Cosa spesso associata alla perdita delle licenze di Access. Nel caso (E SOLO IN QUESTO CASO) si abbia installato VB5 e/o Access 97 e' possibile scaricarsi da www.spippolatori.com il mio program...
Dettagli