X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=socket.tex;h=e20c38800ce3e087de70946678e1a2854d80be31;hp=4f18f9f098d4f915875d4c56d69e0adc440e86be;hb=d99b4995b23505a9afde30adf3a716aa7a55f0e9;hpb=dfa5facee2cc3dd4d66f2397911526770df7cb22 diff --git a/socket.tex b/socket.tex index 4f18f9f..e20c388 100644 --- a/socket.tex +++ b/socket.tex @@ -75,14 +75,13 @@ dei file che contiene i puntatori alle opportune strutture usate dal kernel ed allocate per ogni processo, (la stessa usata per i files e le pipes [NdA verificare!]). -Il prototipo della funzione è definito nell'header \texttt{sys/socket.h}, la -funzione prende tre parametri, il dominio del socket (che definisce la +La funzione prende tre parametri, il dominio del socket (che definisce la famiglia di protocolli, vedi \secref{sec:sock_domain}), il tipo di socket (che definisce lo stile di comunicazione vedi \secref{sec:sock_type}) e il protocollo; in genere quest'ultimo è indicato implicitamente dal tipo di socket, per cui viene messo a zero (con l'eccezione dei \textit{raw socket}). -\begin{prototype}{int socket(int domain, int type, int protocol)} +\begin{prototype}{sys/socket.h}{int socket(int domain, int type, int protocol)} La funzione restituisce un intero positivo se riesce, e -1 se fallisce, in quest'ultimo caso la variabile \texttt{errno} è settata con i seguenti @@ -118,7 +117,7 @@ altro nome con cui si indicano i domini. A ciascun tipo di dominio corrisponde un analogo nome simbolico che inizia per \texttt{AF\_} da \textit{address family}, e che identifica il formato degli -indirizzi usati in quel dominio; le man pages di linux si riferiscono a questi +indirizzi usati in quel dominio; le man pages di Linux si riferiscono a questi anche come \textit{name space}, (nome che però il manuale della glibc riserva ai domini) e che identifica il formato degli indirizzi usati in quel dominio. @@ -131,7 +130,7 @@ supportino diverse strutture di indirizzi, per cui nella pratica questi due nomi sono equivalenti e corrispondono agli stessi valori. I domini (e i relativi nomi simbolici), così come i nomi delle famiglie di -indirizzi sono definiti dall'header \textit{socket.h}. In linux le famiglie di +indirizzi sono definiti dall'header \textit{socket.h}. In Linux le famiglie di protocolli disponibili sono riportate in \ntab. \begin{table}[htb] @@ -151,13 +150,13 @@ protocolli disponibili sono riportate in \ntab. PF\_APPLETALK & Appletalk & ddp(7) \\ PF\_PACKET & Low level packet interface & packet(7) \\ \end{tabular} - \caption{Famiglie di protocolli definiti in linux} + \caption{Famiglie di protocolli definiti in Linux} \label{tab:net_pf_names} \end{table} Non tutte le famiglie di protocolli sono accessibili dall'utente generico, ad esempio in generale tutti i socket di tipo \texttt{SOCK\_RAW} possono essere -creati solo da processi che hanno i provilegi di root (cioè effective uid +creati solo da processi che hanno i privilegi di root (cioè effective uid uguale a zero) o la capability \texttt{CAP\_NET\_RAW}. @@ -167,7 +166,7 @@ uguale a zero) o la capability \texttt{CAP\_NET\_RAW}. La scelta di un dominio non comporta però la scelta dello stile di comunicazione, questo infatti viene a dipendere dal protocollo che si andrà ad utilizzare fra quelli disponibili nella famiglia scelta. Le API permettono di -scegliere lo stile di comunicazione indicando il tipo di socket; linux e le +scegliere lo stile di comunicazione indicando il tipo di socket; Linux e le glibc mettono a disposizione i seguenti tipi di socket (che il manuale della glibc chiama \textit{styles}) definiti come \texttt{int} in \texttt{socket.h}: @@ -269,7 +268,7 @@ in \nfig: \begin{figure}[!htbp] \footnotesize - \begin{lstlisting}{} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} struct sockaddr { sa_family_t sa_family; /* address family: AF_xxx */ char sa_data[14]; /* address (protocol-specific) */ @@ -285,7 +284,7 @@ invocano dette funzioni passando l'indirizzo di un protocollo specifico occorrerà eseguire un casting del relativo puntatore. I tipi di dati che compongono la struttura sono stabiliti dallo standard -Posix.1g, riassunti in \ntab\ con i rispettivi file di include in cui sono +POSIX.1g, riassunti in \ntab\ con i rispettivi file di include in cui sono definiti; la struttura è invece definita nell'include file \texttt{sys/socket.h} @@ -315,14 +314,14 @@ definiti; la struttura \hline \end{tabular} \caption{Tipi di dati usati nelle strutture degli indirizzi, secondo quanto - stabilito dallo standard Posix.1g} + stabilito dallo standard POSIX.1g} \label{tab:sock_data_types} \end{table} In alcuni sistemi la struttura è leggermente diversa e prevede un primo membro aggiuntivo \texttt{uint8\_t sin\_len} (come riportato da R. Stevens nei suoi libri). Questo campo non verrebbe usato direttamente dal programmatore e non è -richiesto dallo standard Posix.1g, in linux pertanto non sussiste. Il campo +richiesto dallo standard POSIX.1g, in Linux pertanto non sussiste. Il campo \texttt{sa\_family\_t} era storicamente un \texttt{unsigned short}. Dal punto di vista del programmatore l'unico uso di questa struttura è quello @@ -341,12 +340,12 @@ I socket di tipo \texttt{PF\_INET} vengono usati per la comunicazione attraverso internet; la struttura per gli indirizzi per un socket internet (IPv4) è definita come \texttt{sockaddr\_in} nell'header file \texttt{netinet/in.h} e secondo le man page ha la forma mostrata in \nfig, -conforme allo standard Posix.1g. +conforme allo standard POSIX.1g. \begin{figure}[!htbp] \footnotesize - \begin{lstlisting}{} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET */ u_int16_t sin_port; /* port in network byte order */ @@ -378,7 +377,7 @@ usare la funzione \texttt{bind} su queste porte. Il membro \texttt{sin\_addr} contiene l'indirizzo internet dell'altro capo della comunicazione, e viene acceduto sia come struttura (un resto di una -implementazione precedente in cui questa era una union usata per accedere alle +implementazione precedente in cui questa era una \texttt{union} usata per accedere alle diverse classi di indirizzi) che come intero. Infine è da sottolineare che sia gli indirizzi che i numeri di porta devono @@ -391,14 +390,14 @@ problema e le relative soluzioni). \subsection{La struttura degli indirizzi IPv6} \label{sec:sock_sa_ipv6} -Essendo IPv6 una estenzione di IPv4 i socket di tipo \texttt{PF\_INET6} sono +Essendo IPv6 una estensione di IPv4 i socket di tipo \texttt{PF\_INET6} sono sostanzialmente identici ai precedenti; la parte in cui si trovano praticamente tutte le differenze è quella della struttura degli indirizzi. La struttura degli indirizzi è definita ancora in \texttt{netinet/in.h}. \begin{figure}[!htbp] \footnotesize - \begin{lstlisting}{} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} struct sockaddr_in6 { u_int16_t sin6_family; /* AF_INET6 */ u_int16_t sin6_port; /* port number */ @@ -418,11 +417,11 @@ struct in6_addr { Il campo \texttt{sin6\_family} deve essere sempre settato ad \texttt{AF\_INET6}, il campo \texttt{sin6\_port} è analogo a quello di IPv4 e -segue le stesse regole; il campo \texttt{sin6\_flowinfo} è a dua volta diviso +segue le stesse regole; il campo \texttt{sin6\_flowinfo} è a sua volta diviso in tre parti di cui i 24 bit inferiori indicano l'etichetta di flusso, i successivi 4 bit la priorità e gli ultimi 4 sono riservati; questi valori fanno riferimento ad alcuni campi specifici dell'header dei pacchetti IPv6 -(vedi \secref{sec:appA_ipv6}) ed il loro uso è sperimentale. +(vedi \secref{sec:IP_ipv6head}) ed il loro uso è sperimentale. Il campo \texttt{sin6\_addr} contiene l'indirizzo a 128 bit usato da IPv6, infine il campo \texttt{sin6\_scope\_id} è un campo introdotto con il kernel @@ -445,7 +444,7 @@ definita nel file di header \texttt{sys/un.h}. \begin{figure}[!htbp] \footnotesize - \begin{lstlisting}{} + \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} #define UNIX_PATH_MAX 108 struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX */ @@ -499,7 +498,7 @@ utile anche in seguito. \subsection{La \textit{endianess}} \label{sec:sock_endianess} -La rappresentazione di un numbero binario in un computer può essere fatta in +La rappresentazione di un numero binario in un computer può essere fatta in due modi, chiamati rispettivamente \textit{big endian} e \textit{little endian} a seconda di come i singoli bit vengono aggregati per formare le variabili intere (in diretta corrispondenza a come sono poi in realtà cablati @@ -516,14 +515,16 @@ numero. Il caso opposto, in cui si parte dal bit meno significativo per lo stesso motivo \textit{big endian}. La \textit{endianess} di un computer dipende essenzialmente dalla architettura -hardware usata; intel e digital usano il little endian, motorola, ibm, sun +hardware usata; Intel e Digital usano il little endian, Motorola, IBM, Sun (sostanzialmente tutti gli altri) usano il big endian. Il formato della rete è -anch'esso big endian. Esistono poi anche dei processori che possono scegliere -il tipo di formato all'avvio e alcuni, come il PowerPC o l'intel i860, possono -pure passare da un tipo all'altro con una specifica istruzione; in ogni caso -in linux l'ordinamanento è definito dall'archiettura e anche se questi -cambiamenti sono possibili anche dopo che il sistema è avviato, non vengono -mai eseguiti. +anch'esso big endian, quello del bus PCI è little endian, quello del bus VME è +big endian. + +Esistono poi anche dei processori che possono scegliere il tipo di formato +all'avvio e alcuni, come il PowerPC o l'Intel i860, possono pure passare da un +tipo di ordinamento all'altro con una specifica istruzione; in ogni caso in +Linux l'ordinamento è definito dall'architettura e anche se questi cambiamenti +sono possibili anche dopo che il sistema è avviato, non vengono mai eseguiti. \subsection{Le funzioni per il riordinamento} \label{sec:sock_func_ord} @@ -532,26 +533,29 @@ Il problema connesso all'endianess di architettura all'altra i dati vengono interpretati in maniera diversa, e ad esempio nel caso dell'intero a 16 bit ci si ritroverà con i due bytes in cui è suddiviso scambiati di posto, e ne sarà quindi invertito l'ordine di lettura -per cui, per riavere il valore originale dovrenno essere rovesciati. - -Per questo motivo si usano le seguenti funzioni di conversione (i cui -prototipi sono definiti in \texttt{netinet/in.h}) che servono a tener conto -automaticamente della possibile differenza fra l'ordinamento usato sul -computer e quello che viene usato nelle trasmissione sulla rete; queste -funzioni sono:{ -\begin{prototype}{unsigned long int htonl(unsigned long int hostlong)} +per cui, per riavere il valore originale dovranno essere rovesciati. + +Per questo motivo si usano le seguenti funzioni di conversione che servono a +tener conto automaticamente della possibile differenza fra l'ordinamento usato +sul computer e quello che viene usato nelle trasmissione sulla rete; queste +funzioni sono: +\begin{prototype}{netinet/in.h} +{unsigned long int htonl(unsigned long int hostlong)} Converte l'intero a 32 bit \texttt{hostlong} dal formato della macchina a quello della rete. \end{prototype} -\begin{prototype}{unsigned sort int htons(unsigned short int hostshort)} +\begin{prototype}{netinet/in.h} +{unsigned short int htons(unsigned short int hostshort)} Converte l'intero a 16 bit \texttt{hostshort} dal formato della macchina a quello della rete. \end{prototype} -\begin{prototype}{unsigned long int ntonl(unsigned long int netlong)} +\begin{prototype}{netinet/in.h} +{unsigned long int ntonl(unsigned long int netlong)} Converte l'intero a 32 bit \texttt{netlong} dal formato della rete a quello della macchina. \end{prototype} -\begin{prototype}{unsigned sort int ntons(unsigned short int netshort)} +\begin{prototype}{netinet/in.h} +{unsigned sort int ntons(unsigned short int netshort)} Converte l'intero a 16 bit \texttt{netshort} dal formato della rete a quello della macchina. \end{prototype} @@ -571,10 +575,9 @@ codice su tutte le architetture. \texttt{inet\_ntoa}} \label{sec:sock_func_ipv4} -Un secondo insieme di funzioni di manipolazione (i cui prototipi sono definiti -in \texttt{arpa/inet.h}) serve per passare dal formato binario usato nelle -strutture degli indirizzi alla rappresentazione dei numeri IP che si usa -normalente. +Un secondo insieme di funzioni di manipolazione serve per passare dal formato +binario usato nelle strutture degli indirizzi alla rappresentazione dei numeri +IP che si usa normalmente. Le prime tre funzioni di manipolazione riguardano la conversione degli indirizzi IPv4 da una stringa in cui il numero di IP è espresso secondo la @@ -582,15 +585,16 @@ cosiddetta notazione \textit{dotted-decimal}, (cio \texttt{192.160.0.1}) al formato binario (direttamente in \textit{network order}) e viceversa; in questo caso si usa la lettera $a$ come mnemonico per indicare la stringa. Dette funzioni sono: -\begin{prototype}{int inet\_aton(const char *src, struct in\_addr *dest)} - Converte la stringa puntata da \texttt{src} nell'indirizzo binario da - memorizzare all'indirizzo puntato da \texttt{dest}, restituendo 0 in caso - di successo e 1 in caso di fallimento (è espressa in questa forma in modo da - poterla usare direttamente con il puntatore usato per passare la struttura - degli indirizzi). Se usata con \texttt{dest} inizializzato a - \texttt{NULL} effettua la validazione dell'indirizzo. -\end{prototype} -\begin{prototype}{in\_addr\_t inet\_addr(const char *strptr)} +\begin{prototype}{arpa/inet.h} + {int inet\_aton(const char *src, struct in\_addr *dest)} Converte la stringa + puntata da \texttt{src} nell'indirizzo binario da memorizzare all'indirizzo + puntato da \texttt{dest}, restituendo 0 in caso di successo e 1 in caso di + fallimento (è espressa in questa forma in modo da poterla usare direttamente + con il puntatore usato per passare la struttura degli indirizzi). Se usata + con \texttt{dest} inizializzato a \texttt{NULL} effettua la validazione + dell'indirizzo. +\end{prototype} +\begin{prototype}{arpa/inet.h}{in\_addr\_t inet\_addr(const char *strptr)} Restituisce l'indirizzo a 32 bit in network order a partire dalla stringa passata come parametro, in caso di errore restituisce il valore \texttt{INADDR\_NONE} che tipicamente sono trentadue bit a uno; questo @@ -598,7 +602,7 @@ indicare la stringa. Dette funzioni sono: valido, non può essere usata con questa funzione; per questo motivo essa è generalmente deprecata in favore della precedente. \end{prototype} -\begin{prototype}{char *inet\_ntoa(struct in\_addr addrptr)} +\begin{prototype}{arpa/inet.h}{char *inet\_ntoa(struct in\_addr addrptr)} Converte il valore a 32 bit dell'indirizzo (espresso in network order) restituendo il puntatore alla stringa che contiene l'espressione in formato dotted decimal. Si deve tenere presente che la stringa risiede in memoria @@ -611,46 +615,59 @@ indicare la stringa. Dette funzioni sono: Le tre funzioni precedenti sono limitate solo ad indirizzi IPv4, per questo motivo è preferibile usare le due nuove funzioni \texttt{inet\_pton} e -\texttt{inet\_ntop} che possono convertire anche gli indirizzi IPv6 (secondo -lo schema in \nfig). Anche in questo caso le lettere $n$ e $p$ sono degli -mnemonici per ricordare il tipo di conversione effettuata e stanno per -\textit{presentation} e \textit{numeric}. - -\begin{figure}[htb] - \centering - - \caption{Schema della rappresentazioni utilizzate dalle funzioni di - conversione \texttt{inet\_pton} e \texttt{inet\_ntop} } - \label{fig:sock_inet_conv_func} - -\end{figure} - -Entrambe le funzioni accettano l'argomento \texttt{family} che indica il tipo -di indirizzo e può essere \texttt{AF\_INET} o \texttt{AF\_INET6}. Se la -famiglia indicata non è valida entrambe le funzioni ritornano un valore -negativo e settano la variabile \texttt{errno} al valore -\texttt{EAFNOSUPPORT}. I prototipi delle suddette funzioni sono i seguenti: -\begin{prototype}{int inet\_pton(int family, const char *src, void *dest)} - Converte la stringa puntata da \texttt{src} nell'indirizzo binario da - memorizzare all'indirizzo puntato da \texttt{dest}, restituendo 0 in caso di - successo e 1 in caso di fallimento. +\texttt{inet\_ntop} che possono convertire anche gli indirizzi IPv6. Anche in +questo caso le lettere $n$ e $p$ sono degli mnemonici per ricordare il tipo di +conversione effettuata e stanno per \textit{presentation} e \textit{numeric}. + +% \begin{figure}[htb] +% \centering + +% \caption{Schema della rappresentazioni utilizzate dalle funzioni di +% conversione \texttt{inet\_pton} e \texttt{inet\_ntop} } +% \label{fig:sock_inet_conv_func} + +% \end{figure} + +Entrambe le funzioni accettano l'argomento \texttt{af} che indica il tipo di +indirizzo e può essere \texttt{AF\_INET} o \texttt{AF\_INET6}. Se la famiglia +indicata non è valida entrambe le funzioni settano la variabile \texttt{errno} +al valore \texttt{EAFNOSUPPORT}. I prototipi delle suddette funzioni sono i +seguenti: +\begin{prototype}{sys/socket.h} + {int inet\_pton(int af, const char *src, void *addr\_ptr)} Converte la + stringa puntata da \texttt{src} nell'indirizzo IP da memorizzare + all'indirizzo puntato da \texttt{addr\_ptr}, la funzione restituisce un + valore positivo in caso di successo, e zero se la stringa non rappresenta un + indirizzo valido, e negativo se \var{af} specifica una famiglia di indirizzi + non valida. \end{prototype} -\begin{prototype}{char *inet\_ntop(int family, const void *src, char *dest, - size\_t len)} - Converte la struttura dell'indirizzo puntata da \texttt{src} in una stringa - che viene copiata nel buffer puntato dall'indirizzo \texttt{dest}; questo - deve essere preallocato dall'utente e la lunghezza deve essere almeno + +\begin{prototype}{sys/socket.h} + {char *inet\_ntop(int af, const void *addr\_ptr, char *dest, size\_t len)} + Converte la struttura dell'indirizzo puntata da \texttt{addr\_ptr} in una + stringa che viene copiata nel buffer puntato dall'indirizzo \texttt{dest}; + questo deve essere preallocato dall'utente e la lunghezza deve essere almeno \texttt{INET\_ADDRSTRLEN} in caso di indirizzi IPv4 e \texttt{INET6\_ADDRSTRLEN} per indirizzi IPv6; la lunghezza del buffer deve comunque venire specificata attraverso il parametro \texttt{len}. - + La funzione restituisce un puntatore non nullo a \texttt{dest} in caso di successo e un puntatore nullo in caso di fallimento, in quest'ultimo caso viene settata la variabile \texttt{errno} con il valore \texttt{ENOSPC} in caso le dimensioni dell'indirizzo eccedano la lunghezza specificata da - \texttt{len}. + \texttt{len} o \macro{ENOAFSUPPORT} in caso \var{af} non sia una famiglia di + indirizzi valida. \end{prototype} +Gli indirizzi vengono cnovertiti da/alle rispettive strutture di indirizzo +(\var{struct in\_addr} per IPv4, e \var{struct in6\_addr} per IPv6), che +devono essere precedentemente allocate e passate attraverso il puntatore +\var{addr\_ptr}; il parametro \var{dest} di \func{inet\_ntop} non può essere +nullo e deve essere allocato precedentemente. + +Il formato usato per gli indirizzi in formato di presentazione è la notazione +\textit{dotted decimal} per IPv4 e quella descritta in +\secref{sec:IP_ipv6_notation} per IPv6. \section{Il comportamento delle funzioni di I/O} \label{sec:sock_io_behav}