2011-09-19 9 views
11

Gestisco GPSD, un demone di servizio open source ampiamente distribuito che monitora i GPS e altri sensori geodetici. Ascolta le connessioni client-applicazione sulla porta 2947 su IPv4 e IPv6. Per motivi di sicurezza e privacy, normalmente è in ascolto solo sull'indirizzo di loopback, ma esiste un'opzione -G per il daemon che deve essere ascoltato su qualsiasi indirizzo.Come ascoltare su tutti gli indirizzi IPV6 usando l'API C socket

Il problema: l'opzione -G funziona in IPv4, ma non riesco a capire come farlo funzionare con IPv6. Il metodo che dovrebbe funzionare in base a vari esempi di tutorial non lo fa, producendo invece un errore che suggerisce che l'indirizzo è già in uso. Sto cercando aiuto per risolvere questo problema da persone con esperienza con la programmazione di rete IPv6.

codice pertinente è in http://git.berlios.de/cgi-bin/gitweb.cgi?p=gpsd;a=blob;f=gpsd.c;h=ee2156caf03ca23405f57f3e04e9ef306a75686f;hb=HEAD

Questo codice funziona correttamente in casi sia il -G e non -G sotto IPv4, come facilmente si verifica con -l netstat.

Ora osservare intorno alla riga 398 dopo "caso AF_INET6:". L'opzione listen_global è impostata da -G; quando è falso, il codice ha successo. Non v'è attualmente seguita da un commento, ereditato da un contributore sconosciuta, che si legge come questo:

/* else */ 
     /* BAD: sat.sa_in6.sin6_addr = in6addr_any; 
    * the simple assignment will not work (except as an initializer) 
    * because sin6_addr is an array not a simple type 
    * we could do something like this: 
    * memcpy(sat.sa_in6.sin6_addr, in6addr_any, sizeof(sin6_addr)); 
    * BUT, all zeros is IPv6 wildcard, and we just zeroed the array 
    * so really nothing to do here 
    */ 

Secondo vari esempi del tutorial che ho guardato in su, l'assegnazione "sat.sa_in6.sin6_addr = in6addr_any;" è (nonostante il commento) corretto, e lo fa compilare. Tuttavia, l'avvio con -G non riesce a sostenere che l'indirizzo di ascolto è già in uso.

È l'assegnazione "sat.sa_in6.sin6_addr = in6addr_any;" nominalmente corretto qui? Cos'altro, se non altro, mi sto perdendo?

+0

Hai provato a camminare sul demone? – jpalecek

risposta

19

Il motivo per cui l'indirizzo è già in uso è perché su molti stack di rete IPv6, per impostazione predefinita un socket IPv6 ascolterà sia IPv4 che IPv6 allo stesso tempo. Le connessioni IPv4 verranno gestite in modo trasparente e mappate a subset of the IPv6 space. Tuttavia, ciò significa che non è possibile eseguire il binding a un socket IPv6 sulla stessa porta di un socket IPv4 senza modificare le impostazioni sul socket IPv6. Ha senso?

solo fare questo prima della chiamata a bind (questo è preso da uno dei miei progetti):

int on = 1; 
if (addr->sa_family == AF_INET6) { 
    r = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); 
    if (r) 
     /* error */ 
} 

Purtroppo, non v'è alcun valore di default tra le piattaforme per IPV6_V6ONLY - che in pratica significa è sempre necessario accendilo o spegnilo esplicitamente se ti interessa, a meno che non ti interessi delle altre piattaforme. Linux lascia disattivata per impostazione predefinita, Windows lascia di default ...

+1

L'impostazione predefinita di Linux è in realtà da sysctl. Quindi non puoi fare affidamento sul default in assoluto. Ma se il sysadmin non lo ha cambiato, lo fa automaticamente su off. (spento è l'IMO predefinito più ragionevole). –

+1

La tua risposta è corretta e il mio bug è stato corretto. Grazie. – ESR

1

Da uno sguardo nei file di includere un sistema Linux a caso, in6addr_any viene dichiarata in questo modo:

extern const struct in6_addr in6addr_any;  /* :: */ 
extern const struct in6_addr in6addr_loopback; /* ::1 */ 
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } 

Così, forse la vicinanza l'array INIT ha confuso chiunque abbia lasciato quel commento nelle sorgenti di GPSD. Il tipo effettivo è chiaramente struct in6_addr, che è assegnabile.

Mi sono guardato intorno e ho trovato alcuni suggerimenti che suggerivano che se IPv4 sta già ascoltando l'indirizzo "qualsiasi", IPv6 non può anche. Forse è questo che ti sta mordendo.

+0

La seconda parte della diagnosi è corretta (vedi la risposta di Dietrich Epp) e sospetto che abbiate ragione anche per la prima parte. – ESR

Problemi correlati