2012年5月24日 星期四

Porting applications to IPv6 HowTo

這次是要在linux下將ipv4的程式改成ipv4/ipv6相容的程式。

原文可以看Porting applications to IPv6 HowTo

首先利用sockaddr_storage取代傳統的sockaddr_in。當使用ipv4做溝通時,就將這個struct轉為sockaddr_in,使用ipv6溝通時,就要轉換為sockaddr_in6。sockaddr_storage裏面構造長得很像sockaddr_in和sockaddr_in6。

#if ULONG_MAX > 0xffffffff
# define __ss_aligntype __uint64_t
#else
# define __ss_aligntype __uint32_t
#endif
#define _SS_SIZE 128
#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype)))

struct sockaddr_storage
{
sa_family_t ss_family; /* Address family */
__ss_aligntype __ss_align; /* Force desired alignment. */
char __ss_padding[_SS_PADSIZE];
};

當我要使用的時候,我可以預先做轉好的動作備用。

struct sockaddr_storage sa;
struct sockaddr_in *sa_v4 = (struct sockaddr_in *)&sa;
struct sockaddr_in6 *sa_v6 = (struct sockaddr_in *)&sa;

或是你需要用的時候再做轉換。

(((struct sockaddr_in *)&sa)->sin_addr.s_addr)     --->v4
(((struct sockaddr_in6 *)&sa)->sin6_addr.s6_addr) --->v6

接著,記得系統要build好ipv6的module,那樣的話,bind, recv這些通訊方法通通不用改。


而要分辨現在溝通模式是v4還是v6,可以看ss_family。

if(sa.ss_family == AF_INET){
...
}else if(sa.ss_family == AF_INET6){
...
}

最後就要有耐心的補完v6的邏輯。因為網路位址轉字串,位址比較都和v4不相同。詳細範例可以再看前面提到的Porting applications to IPv6 HowTo

沒有留言: