1

我目前正在尝试开发一个显示 IPv6 流量的应用程序。我对如何提取本地站点和本地计算机的链接本地地址感到困惑。任何指导将不胜感激。

我正在使用的 delphi 中 IPv6 数据包的结构是:

type
 PIPV6HeaderPtr = ^TIPV6Header;
 TIPV6Header = packed record
 ip6_flow       : DWORD;    // 4  bits = version #,// 8  bits = Trafic class,// 20 bits = flow label
ip6_len        : Word;//Cardinal;    // Payload length
//ip6_next       : Cardinal;    // Next Header
  ip6_next       : Byte;    // Next Header
ip6_hops       : Byte;         // Hop Limit
  h_source  : IN6_ADDR;
 h_dest    : IN6_ADDR;
end;

//
// IPv6 extension header format
//
 type
  PIPV6EXTPTR = ^TIPV6EXT;
  TIPV6EXT = packed record
  ip6_next       : Byte;
  ip6_len        : Byte;
  ip6_data       : array[0..1] of Byte;

End;


 type
    PIPV6EXT_FRAGPTR = ^TIPV6EXT_FRAG;
    TIPV6EXT_FRAG    = packed record
    ip6_next       : Byte;
   ip6_reserved   : Byte;
   ip6_offlg      : Word;
   ip6_ident      : DWORD;
 End;

提前致谢。

4

2 回答 2

3

有关什么是站点本地地址和链接本地地址以及它们如何工作的说明,请参见以下说明:

IPv6 教程 – 第 6 部分:站点本地地址和链路本地地址

您可以使用 Win32 APIGetAdapterAddresses()函数来获取本地机器的 IPv6 地址。

于 2013-02-28T19:38:40.237 回答
0

我找到了另一种使用 WSAIoctl 获取地址的方法。我在下面添加我的代码。

使用 WinSock2;// 在网络上广泛可用

   function TForm1.GetIPUsingIoctlMethod(var sInt: string): Boolean;
   var
     s: TSocket;
     wsaD: TWSADATA;
     NumInterfaces: Integer;
     BytesReturned, SetFlags: u_long;
     pAddrInet: SOCKADDR_IN;
     pAddrString: PCHAR;
     PtrA: pointer;
     Buffer: Array[0..20] Of  INTERFACE_INFO_EX;
     i: Integer;
     Local_IpList : TStringList ;
     addrList : LPSOCKET_ADDRESS_LIST ;
     in6 :  PSockAddr;
     protoInfo : WSAProtocol_Info;
     text : Array[1..46] Of Char;
     Buffer1 : DWORD;
     Str : String;

 begin
      result := False;                               // Initialize
      sInt := '';
Try

    WSAStartup($0101, wsaD);                      // Start WinSock
                                                  // You should normally check
                                                  // for errors here :)

    {Create a WSA Socket}
    //s := WSASocketA(AF_INET6,SOCK_STREAM, IPPROTO_IP, nil, 0, 0);

    s:= Socket(AF_INET6,SOCK_STREAM,IPPROTO_IP);

    //s := Socket(AF_INET6, SOCK_STREAM, 0);         // Open a socket
    if (s = INVALID_SOCKET) then exit;

    try                                           // Call WSAIoCtl
      PtrA := @bytesReturned;

      if (WSAIoCtl(s, SIO_ADDRESS_LIST_QUERY, nil, 0, @Buffer, SizeOf(Buffer), PtrA, nil, nil)<> SOCKET_ERROR)
        then
          begin                                       // If ok, find out how
                                                   // many interfaces exist

                Result   := True;
                addrList := LPSOCKET_ADDRESS_LIST(@Buffer);


                DebugLog(' i = ' + IntToStr(addrList.iAddressCount),0);
               // NumInterfaces := BytesReturned div SizeOf(INTERFACE_INFO);

                Local_IpList := TStringList.Create ;
                for i := 0 to addrList.iAddressCount - 1 do        // For every interface
                begin
                   If ( addrList.Address[i].lpSockaddr.sin_family = AF_Inet6) Then
                   Begin
                      in6 := PSockaddr(@addrList.Address[i].lpSockaddr);
                      Buffer1 := SizeOf(Text);
                      //protoInfo.
                      FillChar(Text,SizeOf(Text),#0);
                      If WSAAddressToString(addrList.Address[i].lpSockaddr,addrList.Address[i].iSockaddrLength,
                                          nil,@text,Buffer1) <> 0 Then
                      Begin
                          debuglog('err1 = ' + SysErrorMessage(WSAGetLastError),0);
                      end;
                      Str := Text;
                      DebugLog(' Addr cnt =' + IntToStr(i) + ' = ' + Str,0);
                      Buffer1 := 0;
                      FillChar(Text,SizeOf(Text),#0);
                      //in6.
                      //DebugLog('ip = ' + );
                      //IN6_IS_ADDR_LINKLOCAL
                   end;
                end;

      end
      Else
          sInt := SysErrorMessage(WSAGetLastError);
    except
    end;
  //
  // Close sockets
  //
    CloseSocket(s);
    WSACleanUp;
 Except
 End;

结尾;

debugLog 只是一种写入文本文件的方法。

于 2013-03-05T11:39:59.693 回答