IPv6隧道之船蟲機制的效能分析
全文
(2) IPv6 隧道之船蟲機制的效能分析 A Performance Study on Teredo IPv6 Tunneling Mechanism. 研 究 生:黃祥鳴. Student:Shiang-Ming Huang. 指導教授:林一平. Advisor:Yi-Bing Lin. 吳坤熹. Quincy Wu. 國 立 交 通 大 學 資 訊 工 程 學 系 碩 士 論 文. A Thesis Submitted to Department of Computer Science and Information Engineering College of Electrical Engineering and Computer Science National Chiao Tung University in partial Fulfillment of the Requirements for the Degree of Master in Computer Science and Information Engineering June 2005 Hsinchu, Taiwan, Republic of China. 中華民國九十四年六月.
(3) IPv6 隧道之船蟲機制的效能分析. 學生:黃祥鳴. 指導教授:林一平 教授 吳坤熹 教授. 國立交通大學資訊工程學系碩士班. 摘. 要. 船蟲機利用 IPv4 UDP 通訊協定建立 IPv6 隧道,提供位在私有 IPv4 網路 的 IPv6 主機和國際間另外 IPv6 網路相連,解決一般 IPv6 隧道無法在私有 IPv4 網路建立的問題。鑑於此,在行政院國家資訊通信基本建設專案推動小 組的補助下,我們開發了在 Linux 平台第一個非營利導向的船蟲機制實作。 本論文介紹我們的船蟲伺服器架構和船蟲傳遞器架構,並將我們的實作和世 界上現有的船蟲機制實作就架構方面以及效能方面分析研究。經過我們實際 測試,我們的實作的船蟲機制在傳送 IPv6 封包方面比其它兩個公開實作快 了 42%-75%。. i.
(4) A Performance Study on Teredo IPv6 Tunneling Mechanism. Student:Shiang-Ming Huang. Advisors:Prof. Yi-Bing Lin Prof. Quincy Wu. Department of Computer Science and Information Engineering National Chiao Tung University. ABSTRACT. By tunneling IPv6 packets over IPv4 UDP, Teredo supports IPv6 hosts located within private IPv4 networks for connection with external IPv6 networks. Under National Information and Communication Initiative in Taiwan, we have developed the first non-commercial Linux-based Teredo mechanism. In this thesis, we describe our implementation of Teredo server and Teredo relay, and compare our solution with other Teredo implementations in the public domain. Our study indicates that our solution reduces the tunneling overhead and transmission delay over two other implementations by 42%-75%.. ii.
(5) Acknowledgement This thesis is the result of two years of work whereby I have been accompanied and supported by many people. It is a pleasant aspect that I have now the opportunity to express my gratitude for all of them. I would first like to thank Prof. Yi-Bing Lin (林一平) and Prof. Quincy Wu (吳 坤熹) for their guidance, insight and support throughout the preparation of this thesis. I would like to thank Dr. Whai-En Chen (陳懷恩), Meng-Hsun Ts’ai (蔡孟勳), Wei-Che Huang (黃偉哲) and Jui-Hung Weng (翁瑞鴻) for the helpful discussions about the design of Teredo relay testing environment. I would also like to thank my master committee members, Prof. Ai-Chun Pang (逄愛君) and Prof. Shun-Ren Yang (楊舜仁) for their helpful comments and suggestions. My colleagues of Laboratory 117 all gave me the feeling of being at home at work. Many thanks for being your colleague. I feel a deep sense of gratitude for my parents who formed part of my vision and taught me the good things that really matter in life. I am grateful for my three sisters for rendering me the sense and the value of brotherhood. I am glad to be one of them. Finally, I would like to thank all my friends who inspire me or make me feel confidence to accomplish this thesis.. Shiang-Ming Huang June 2005. iii.
(6) Contents 摘要…………………………………………………………………………….………...i ABSTRACT………………………………………………………………….………….ii Acknowledgement………………………………………………………………………iii Contents………………………………………………………………………………....iv List of Figures…………………………………………………………………………...vi List of Tables…………………………………………………………………………...vii Chapter 1. Introduction……………………………………………………………...1. Chapter 2. The Teredo Mechanism………………………………………………….3. 2.1 Teredo Architecture………………………………………………….…….3 2.2 Address Mapping on NAT………………………………………………...4 2.3 Teredo Addressing…………………………………………………………6 2.4 Packet Delivery through Teredo………………………………..………….8 Chapter 3. Three Teredo Implementations………………………………….……...10. 3.1 Teredo Server…………………………………………………………….11 3.1.1. NICI-Teredo Server………………………………………….11. iv.
(7) 3.1.2 3.2. Chapter 4. 6WIN-Teredo Server and Miredo-Teredo Server…………...12. Teredo Relay………………………………………………….…….…..13 3.1.1. NICI-Teredo Relay…………………………………………..13. 3.2.2. 6WIND-Teredo Relay……………………………………….15. 3.2.3. Miredo-Teredo Relay………………………………………..17. Performance Evaluation of Teredo Relay Implementations..…………..20. 4.1. Measurement Environment……………………………………………..20. 4.2. Experimental Result…………………………………………….……...21. Chapter 5. Conclusions…………………………………………………………….25. Bibliography……………………………………………………………………………26 Appendix A. Decapsulation Latency Histograms…………………………………….28. Appendix B. The NICI-Teredo Server Program……………………………………...30. B.1 teredo_server.h………………………………………………….30 B.2 teredo_server.c………………………………………………….31 Appendix C. The NICI-Teredo Relay Program……………………………….……...39. C.1 teredo.h…………………………………………………….…….…39 C.2 bubble.h……………………………………………………………..41 C.3 teredo.c………………………………………………………….….45. v.
(8) List of Figures Figure 1. Teredo architecture.……………………………….……….……………….….4 Figure 2. An entry in the address mapping table.……….………..………..…………….5 Figure 3. Teredo IPv6 address format.………..……….……….……….……………….6 Figure 4. Communication between a Teredo client and an IPv6 host..……….…………8 Figure 5. Software architecture of the NICI-Teredo server..………..……….…………12 Figure 6. Software architecture of the NICI-Teredo relay..………..……….………….14 Figure 7. Software architecture of the 6WIND-Teredo relay..……….………………...16 Figure 8. Software architecture of the Miredo-Teredo relay.……….……….…………18 Figure 9. The test environment..……….……….……….……….……….…………….21 Figure 10. Encapsulation latency histograms of the Teredo relays (1280 bytes)………22 Figure 11. Encapsulation latency histograms of the Teredo relays (512 bytes).……….23 Figure 12. Encapsulation latency histograms of the Teredo relays (64 bytes).………...23 Figure 13. Decapsulation latency histograms of the Teredo relays (1280 bytes)………28 Figure 14. Decapsulation latency histograms of the Teredo relays (512 bytes).……….29 Figure 15. Decapsulation latency histograms of the Teredo relays (64 bytes).………...29. vi.
(9) List of Tables Table 1. Average processing latency..……………………………….……….………...22. vii.
(10) Chapter 1 Introduction After three decades of evolution in Internet technologies, IETF (Internet Engineering Task Force) has developed Internet Protocol version 6 (IPv6) as the next generation Internet protocol. In comparison with the existing Internet Protocol version 4 (IPv4), IPv6 provides larger address space, more efficient routing mechanism, better support for security and quality of service (QoS).. During IPv6 deployment, many existing IP networks remain to support IPv4 only. Because each site may deploy IPv6 in incremental fashion, it is unrealistic to assume a single flag day to upgrade all IPv4 networks to IPv6. To facilitate the transition for IPv4 to IPv6 migration, tunneling techniques are utilized to carry IPv6 traffic through IPv4 networks [1].. In existing IPv6-in-IPv4 tunneling mechanisms such as configured tunnel & automatic tunnel [1], 6to4 tunnel [2] and tunnel broker [3], both end points of a tunnel must possess public IPv4 addresses. Although public IPv4 addresses may be available in some typical scenarios, many Internet service providers, especially WLAN (wireless local area network) and GPRS (general packet radio service) [4], may only provide private IPv4 addresses to their customers, and NAT (network address translation) [5] is required to establish Internet connectivity. Hence,. 1.
(11) IPv6 users within private IPv4 networks would not be able to establish tunnels to public IPv6 networks. This issue turns out to be one of the major obstacles in IPv6 deployment.. Several IPv6 tunneling solutions for private IPv4 networks with NAT have been proposed, including virtual private network (VPN) and user datagram protocol (UDP) tunnel [6]. These solutions provide IPv6 connectivity for private hosts, but require manual configuration at the user end of a tunnel. This configuration task is not transparent to users, and is not easy for novice users. Therefore, it is not suitable for large private IPv4 networks. Moreover, in these approaches, only one static tunnel server is assigned to relay all IPv6 packets of a host in the private network. This tunnel server may potentially become the bottleneck, and it is very likely that the traffic follows a “dog leg” route from the source to the tunnel server and then to the destination, resulting in a non-optimal routing path. The above issues can be resolved by Teredo [7], an automatic tunneling mechanism with the capability to traverse NATs1.. Under the support of NICI (National Information and Communication Initiative), we have developed the first non-commercial Linux-based Teredo to speed up the IPv6 deployment. This thesis describes our Teredo implementation and then compares it with other public-domain Teredo solutions.. 1. Recently, an enhanced model of UDP tunnel called “Silkroad” [8] was proposed to alleviate. the bottleneck issue. However, some critical algorithms of Silkroad are still missing at the time when this thesis is written.. 2.
(12) Chapter 2 The Teredo Mechanism This chapter first introduces Teredo architecture and address mapping on NAT, and then describes how Teredo applies this address mapping technique to help tunneling IPv6 through NAT. Finally; we conclude this chapter with an example that shows how an IPv6 packet is delivered through Teredo.. 2.1 Teredo Architecture By tunneling IPv6 packets over IPv4 UDP through NATs, Teredo provides IPv6 connectivity for IPv6 hosts within private IPv4 networks. The Teredo architecture is illustrated in Figure 1, which consists of a Teredo server (Figure 1 (a)), several Teredo clients (Figure 1 (b)) and Teredo relays (Figure 1 (c)). A Teredo client is implemented at an IPv6 host in a private IPv4 network (Figure 1 (d)) that connects to public IPv4 network (Figure 1 (e)) through NAT (Figure 1 (f)). A Teredo server assists a Teredo client to obtain an IPv6 address for IPv6 network access. For IPv6 packets sent from the IPv6 network, the Teredo relay encapsulates these packet in IPv4 UDP and forwards them to the destination Teredo client in a private IPv4 network. In the reverse direction, the Teredo relay decapsulates IPv4 UDP packets sent from the Teredo client to the IPv6 network (Figure 1 (g)). To broadcast its identity, every Teredo. 3.
(13) 1 in relay advertises an IPv6 address prefix 3FFE:831F::/32 to the IPv6 network (path ○. Figure 1). Through the advertisement, the IPv6 hosts (Figure 1 (h)) select appropriate Teredo relays such that all IPv6 packets sent from these IPv6 hosts to a Teredo client are routed to Teredo relays closest to the packet sources. Therefore the traffic load to a Teredo client can be dynamically adjusted among Teredo relays with optimal routing.. IPv4 network. 4. (e) (a). qualification. (f) NAT. 3. Public IPv4: 1.1.1.1 Private IPv4: 192.168.0.1. (c). 1. 2 (b). Teredo server UDP: 3544 IPv4: 3.3.3.3 IPv6: 2001:3:3:3::3. Private IPv4 network. Teredo relay UDP: 3544 IPv4: 2.2.2.2 IPv6: 2001:2:2:2::2. (d) Teredo client UDP: 4096 IPv4: 192.168.0.2 IPv6: 3FFE:831F:0303:0303:8000:E148:FEFE:FEFE. advertisement 3FFE:831F::/32. IPv6 network. (g). (h) IPv6 host IPv6: 2001:4:4:4::4. Figure 1. Teredo architecture. 2.2 Address Mapping on NAT In Figure 1, the IPv4 address of the Teredo server is 3.3.3.3. The NAT is equipped with two network interfaces: the WAN interface (to the public network) has the public IPv4 address 1.1.1.1, and the LAN interface (to the private network) has the private IPv4 address 192.168.0.1. The Teredo client is assigned the private IPv4 address 192.168.0.2. The NAT performs private-public address translation for all pass-through packets according to an. 4.
(14) address mapping table. Suppose that the NAT is a full cone NAT2 [9]. The fields of an entry in the NAT address mapping table are illustrated in Figure 2. In this table, the “private IPv4 address” and the “private port” fields store the private transport address of the private end (i.e. IPv4 address plus TCP/UDP port, whose values are 192.168.0.2 and 4096 for the example in Figure 1). The “transport protocol” field stores the transport protocol type (TCP or UDP). The “public IPv4 address” and the “public port” fields store the public transport address assigned by the NAT. The values in these fields (IPv4 address 1.1.1.1 and port 7863 in this example) are used to replace the private transport address. This public transport address for a private IPv4 host is crucial for IPv4 UDP packets passing through the NAT. When a host in the public IPv4 network sends an IPv4 UDP packet to this transport address (1.1.1.1:7863), the NAT dispatches this packet to the designated private IPv4 host with the help of the address mapping table.. transport protocol. private IPv4 address. private port. public IPv4 address. public port. Figure 2. An entry in the address mapping table. 2. When an internal host within a private network sends a packet to an external host, a NAT. maps the private transport address of the internal host to a unique public transport address. Thereafter, a public host can send packets to the private host by delivering them to the mapped public transport address. However, different types of NATs have different rules to handle incoming packets. The full cone NAT allows packets from all public hosts to pass through, while a restricted cone NAT allows an external host (with IP address X) sending a packet to the private transport address only if the private transport address had previously sent a packet to IP address X.. 5.
(15) 2.3 Teredo Addressing As an automatic tunneling mechanism, Teredo embeds the NAT traversal information in its 128-bit IPv6 address. A Teredo IPv6 address format consists of the following fields (see Figure 3).. 3FFE:831F::/32. 32 bits. Teredo server IPv4 address 32 bits. Flag. Obfuscated mapped public UDP port. 16 bits. 16 bits. Obfuscated mapped public IPv4 address 32 bits. Figure 3. Teredo IPv6 address format. The “3FFE:831F::/32” field specifies the IPv6 address prefix for Teredo. The “Teredo server IPv4 address” field indicates the IPv4 address of a Teredo server (e.g. 3.3.3.3 in Figure 1). The “Flag” field indicates the type of NAT (full cone or not) [9]. The “Obfuscated mapped public UDP port” and the “Obfuscated mapped public IPv4 address” fields indicate the public trasnport address assigned by the NAT. This transport address is mapped to the Teredo client’s private transport address. The obfuscation mechanism is needed because some NAT products provide “generic” application layer gateway (ALG) functionality. The generic ALG hunts for IPv4 addresses, either in text or binary formats within a packet, and rewrites them if they match a binding in the address mapping table. When this “smart NAT” handles the payload of pass-through IPv4 packets, it translates any occurrence of IPv4 address in the payload that matches the address to be translated in the IPv4 header (or translates any occurrence of port number in the payload that matches the port to be translated in the TCP/UDP header). Such action certainly interferes with normal Teredo operations. To prevent the smart NAT from. 6.
(16) modifying the Teredo IPv6 addresses in the encapsulated IPv4 UDP packets, obfuscation performs bitwise XOR operation on the original value with 1 to protect it.. At start-up, a Teredo client obtains a Teredo IPv6 address from the Teredo server by 2 →○ 3 in Figure 1). This procedure detects the performing the qualification procedure (path ○. NAT type and informs the Teredo client of the mapped public transport address. As long as the Teredo clients obtain Teredo IPv6 addresses, they are able to communicate with the IPv6 network with the help of Teredo servers and Teredo relays. In Figure 1, the Teredo client uses UDP port 4096 to request a Teredo IPv6 address from the Teredo server. When this packet 2 in Figure 1), the NAT dynamically allocates an available UDP arrives at the NAT (path ○. port (e.g. 7863 in this example) for this connection, and creates an entry in the address mapping table with protocol type UDP, private transport address 192.168.0.2:4096 and public 3 in transport address 1.1.1.1:7863. Then the UDP packet is sent to the Teredo server (path ○. Figure 1). The Teredo server calculates the Teredo IPv6 address for this Teredo client by determining the value of each field as follows:. ‧Prefix (32 bits) = 0x3FFE831F ‧Teredo server IPv4 address (32 bits) = 3.3.3.3 = 0x03030303 ‧Flag (16 bits) = 0x8000 (full cone NAT) ‧Obfuscated mapped public UDP port (16 bits) = 7863♁0xFFFF = 0x1EB7♁0xFFFF = 0xE148 ‧Obfuscated mapped public IPv4 address (32 bits) = 1.1.1.1♁0xFFFFFFFF = 0x01010101♁ 0xFFFFFFFF = 0xFEFEFEFE. 7.
(17) Therefore, the Teredo IPv6 address assigned to this Teredo client by the Teredo server (path 4 in Figure 1) is 3FFE:831F:0303:0303:8000:E148:FEFE:FEFE. ○. 2.4 Packet Delivery through Teredo After qualification, communication between the Teredo client and an IPv6 host can be established.. Teredo server UDP: 3544 IPv4: 3.3.3.3 IPv6: 2001:3:3:3::3. IPv4 network. 2. UDP. Address mapping table on NAT 192.168.0.2 4096 1.1.1.1. 7863. NAT. Public IPv4: 1.1.1.1 Private IPv4: 192.168.0.1. 3 Teredo relay UDP: 3544 IPv4: 2.2.2.2 IPv6: 2001:2:2:2::2. Private IPv4 network. Teredo client UDP: 4096 IPv4: 192.168.0.2 IPv6: 3FFE:831F:0303:0303:8000:E148:FEFE:FEFE. 1 IPv6 network. IPv6 host IPv6: 2001:4:4:4::4. Figure 4. Communication between a Teredo client and an IPv6 host. Figure 4 illustrates how an IPv6 packet is delivered from an IPv6 host to a Teredo client with 1 →○ 2 →○ 3 in Figure 4). the following steps (see path ○. Step 1. The IPv6 packet is sent from the IPv6 host to the Teredo relay. (The IPv6 host selects 1 in Figure 1.) this Teredo relay according to the advertisement; see path ○. 8.
(18) Step 2. The Teredo relay encapsulates the IPv6 packet in an IPv4 UDP packet. The source address is the IPv4 address of the Teredo relay (2.2.2.2), and the source UDP port is 3544. The destination IPv4 address and UDP port of this packet are determined based on the IPv6 address of this Teredo client as follows. The destination address is the restored value derived from the 32-bit “Obfuscated mapped public IPv4 address” field of destination IPv6 address (0xFEFEFEFE♁0xFFFFFFFF = 0x01010101 = 1.1.1.1), and the destination UDP port is the restored value derived from the 16-bit “Obfuscated mapped public UDP port” field of destination IPv6 address (0xE148♁0xFFFF = 0x1EB7 = 7863). The Teredo relay sends the IPv4 UDP packet to the NAT (1.1.1.1:7863) through the IPv4 network.. Step 3. When the NAT receives this IPv4 UDP packet, it translates the destination IPv4 address and UDP port from 1.1.1.1:7863 to 192.168.0.2:4096 according to the address mapping table, and then sends it to the Teredo client in the private IPv4 network.. Upon receipt of the packet, the Teredo client decapsulates the IPv4 UDP packet to obtain the IPv6 packet. With the above steps, IPv6 packets sent from the IPv6 host can successfully pass through the NAT. This example assumes a full cone NAT server. Details of packet transmission for other types of NATs can be found in the Teredo draft [7].. 9.
(19) Chapter 3 Three Teredo Implementations We implemented NICI-Teredo [10] on Linux in year 2003. NICI-Teredo supports the Teredo server and Teredo relay functions that can be installed on a single host or independently on multiple hosts. The Teredo server function is implemented as a user-level daemon, which is illustrated in Figure 5 (a) and the source code is listed in Appendix B. The Teredo relay function is developed with a combination of a user-level program and a kernel-level module as illustrated in Figure 6 (a). The user-level programs deal with the NICI-Teredo configuration, while the kernel-level module supports high-speed IPv6 packet relaying (the source code is listed in Appendix C).. In the same year that we implemented NICI-Teredo, an independent Teredo implementation for FreeBSD was also developed by 6WIND, LIP6 and Euronetlab [11]. In year 2004, Miredo-Teredo was developed on Solaris, FreeBSD, and Linux [12]. In this chapter, we illustrate the software architectures of these Teredo implementations with a focus on Teredo server and Teredo relay.. 10.
(20) 3.1 Teredo Server 3.1.1 NICI-Teredo Server. The NICI-Teredo server (Figure 5 (a)) invokes an IPv6 raw Ethernet socket (Figure 5 (b)) and two IPv4 UDP sockets (Figure 5 (c)) at the Linux kernel to send and receive packets. The 1 ) NICI-Teredo server consists of four components. The packet processor (Figure 5 ○. handles IPv6 packet encapsulation and IPv4 UDP packet decapsulation. The dispatcher 2 ) checks the IPv6 packets delivered from the packet processor and dispatches (Figure 5 ○ 3 ) performs the them to the proper functions. The qualification function (Figure 5 ○. qualification procedure for Teredo clients. This function helps the Teredo client to discover the type of NAT and the mappped public transport address, as described in Chapter 2. The A →○ B →○ C → Teredo server interacts with the Teredo clients for qualification through path ○ D →○ E in Figure 5. For a Teredo client which attempts to communicate with an IPv6 host, ○ 4 ) helps to locate a Teredo relay closest to the the ICMPv6 relay function (Figure 5 ○. destination IPv6 host. This discovery task is achieved by the ICMPv6 echo request sent from A →○ B →○ F →○ G in Figure 5 and the Teredo client to the destination IPv6 host through path ○ 1 →○ 2 →○ 3 in the response sent from the IPv6 host to the Teredo client following path ○. Figure 4. From the response message, the Teredo relay is located for the communication between the Teredo client and the IPv6 host.. 11.
(21) 3.1.2 6WIND-Teredo Server and Miredo-Teredo Server. The 6WIND-Teredo server and Miredo-Teredo server have similar architecture design, and the details are omitted.. NICI-Teredo server D C. packet processor B. 1 User level Kernel level. dispatcher 2. F. E. (a) qualification function 3 ICMPv6 relay function 4 G. A. (c). UDP socket (SOCK_DGRAM). (b). physical interface module. physical interface module. physical interface. physical interface. IPv4 network. IPv6 network. Figure 5. Software architecture of the NICI-Teredo server. 12. Raw Ethernet socket (SOCK_RAW).
(22) 3.2 Teredo Relay 3.2.1 NICI-Teredo Relay. The NICI-Teredo relay (Figure 6 (a)) provides the IPv6 packet relay function by utilizing the IPv6 and IPv4 forwarding mechanisms (Figures 6 (b) and (c)) at the Linux kernel. This 1 ) provides packet Teredo relay consists of three modules. The relay module (Figure 6 ○. encapsulation and decapsulation functions by two callback functions, A ) and udpip6_rcv() (Figure 6 ○ B ), invoked by udpip6_tunnel_xmit() (Figure 6 ○. the IPv6 and the IPv4 forwarding mechanisms. From the IPv6 forwarding mechanism, the relay module receives IPv6 packets for IPv4 UDP encapsulation, and then passes them to the C ). The encapsulated IPv4 forwarding mechanism by IPTUNNEL_XMIT()3 (Figure 6 ○. packets are then delivered to the Teredo clients. In the reverse direction, the tunneled IPv4 UDP packets are also decapsulated into IPv6 by this module, and then passed to the IPv6 forwarding mechanism (i.e. via Linux function netif_rx()) for delivery to the IPv6 D ). The routing management module (Figure 6 ○ 2 ) maintains the networks (Figure 6 ○. packet forwarding plans at the Linux kernel. It configures the IPv6 forwarding plan to route the IPv6 packets to the Teredo clients (i.e. for the packets with the destination IPv6 addresses matching the IPv6 address prefix 3FFE:831F::/32) through the relay module, and configures the IPv4 forwarding plan to dispatch the IPv4 UDP packets from the Teredo clients to the 3. According to the Linux programming convention, the uppercase name IPTUNNEL_XMIT(). refers to a macro, while the lowercase name such as udpip6_rcv() refers to a function. The same convention is used in the 6WIND implementation on FreeBSD.. 13.
(23) 3 ) advertises the IPv6 address relay module. The prefix advertisement module Figure 6 ○. prefix 3FFE:831F::/32 to the IPv6 network so that the IPv6 packets destined to the Teredo clients can be routed to the nearest Teredo relay.. NICI-Teredo Relay (a) prefix advertisement 3 module routing management 2 module. User level Kernel level. (c). C. IPv4 forwarding. B. relay module encapsulation decapsulation. advertisement 3FFE:831F::/32. configuration. 1. (b). A. IPv6 forwarding D. physical interface module. physical interface module. physical interface. physical interface. IPv4 network. IPv6 network advertisement 3FFE:831F::/32. Figure 6. Software architecture of the NICI-Teredo relay. 14.
(24) 3.2.2 6WIND-Teredo Relay. 6WIND-Teredo relay (Figure 7 (a)) provides IPv6 packet relay function by netgraph, a FreeBSD in-kernel networking subsystem. This Teredo relay relies on IPv6 forwarding mechanism (Figure 7 (b)) and socket functions (Figure 7 (c)) at the FreeBSD kernel to provide packet relay function. Unlike NICI-Teredo relay that utilizes a single kernel-level module to provide all packet processing functions, 6WIND-Teredo relay relies on the cooperation of several netgraph submodules and a kernel IPv4 UDP socket to handle the packets. 6WIND-Teredo relay consists of three components. The netgraph module (Figure 7 1 ) utilizes three submodules to deals with IPv6 packet processing. The ○. netisr_dispatch() and ng_iface_output() functions of the ngN submodule send and receive IPv6 packets; the so_pru_sosend() and so_pru_soreceive() functions of the ksocket submodule utilize a kernel IPv4 UDP socket to send and receive the encapsulated packets. These two netgraph submodules interact with each other through the ng_teredo submodule. Specifically, the ng_teredo submodule uses NG_SEND_DATA() and ng_teredo_rcvdata() to send and receive IPv6 packets between the ngN and the ksocket submodules. By the cooperation of these three submodules in the netgraph module, IPv6 packets received by the ngN submodule are written to the kernel’s IPv4 UDP socket by the ksocket submodule, and vice versa. The IPv4 UDP socket provides packet encapsulation and decapsulation functions by delivering an IPv6 packet as the datagram through the socket. 2 ) configures the IPv6 forwarding plan and The routing management module (Figure 7 ○. the interconnection between the netgraph submodules. The prefix advertisement module 3 ) provides similar functions as the prefix advertisement module in the (Figure 7 ○. 15.
(25) NICI-Teredo relay, and the details are omitted.. 6WIND-Teredo Relay. (a) advertisement. prefix advertisement 3 module routing management 2 module. User level Kernel level. netgraph module encapsulation. UDP socket. (c) decapsulation. ksocket. ngN. 3FFE:831F::/32. configuration. 1. (b). IPv6 forwarding. ng_teredo physical interface module. physical interface module. physical interface. physical interface. IPv4 network. IPv6 network advertisement 3FFE:831F::/32. Figure 7. Software architecture of the 6WIND-Teredo relay. 16.
(26) 3.2.3 Miredo-Teredo Relay. The software architecture of the Miredo-Teredo relay (Figure 8 (a)) is quite different from the previous two implementations. Miredo-Teredo relay relies on IPv6 forwarding mechanism (Figure 8 (b)) and an IPv4 UDP socket (Figure 8 (c)) for packet processing. Unlike NICI-Teredo relay that uses a kernel-level packet relay module, Miredo-Teredo relay uses a user-level packet processing module to send and receive the encapsulated packets. This module delivers an IPv6 packet as the encapsulated datagram through the IPv4 UDP socket. 1 ) is built on Miredo-Teredo relay consists of four components. The tun module (Figure 8 ○. the IPv6 protocol stack to send and receive IPv6 packets. The packet processing module 2 ) creates and maintains an IPv4 UDP socket (Figure 8 (c)) for packet (Figure 8 ○. encapsulation and decapsulation. This module provides IPv6 packet relay function by using memcpy() and socket functions (sendto() and recvfrom()) for IPv6 packets delivery A and ○ B ). This between the tun module and the IPv4 UDP socket (see Figures 8 ○. architecture is clearly different from those of NICI-Teredo relay and 6WIND-Teredo relay. On 3 ) and the the other hand, the Miredo-Teredo relay routing management module (Figure 8 ○ 4 ) are similar to those of NICI-Teredo relay and prefix advertisement module (Figure 8 ○. 6WIND-Teredo relay.. 17.
(27) Miredo-Teredo Relay. (a). prefix advertisement 4 module routing management 3 module B User level. packet processing module. advertisement 3FFE:831F::/32. configuration. 2. A. Kernel level. encapsulation UDP socket (c) decapsulation (SOCK_DGRAM). tun module. 1. (b). IPv6 forwarding. physical interface module. physical interface module. physical interface. physical interface. IPv4 network. IPv6 network advertisement 3FFE:831F::/32. Figure 8. Software architecture of the Miredo-Teredo relay. 18.
(28) The Teredo relay design significantly affects the packet transmission performance. The packet processing latency of NICI-Teredo relay is shorter because there are no packet copying operations between the kernel and the user levels. The performance comparison of these Teredo implementations will be elaborated in the next chapter.. As a final remark, the NICI-Teredo relay is implemented as a loadable kernel module [13]. Although kernel hacking effort is required in developing the NICI-Teredo relay, the installation process is very simple and the users do not need to modify or re-compile the Linux kernel.. 19.
(29) Chapter 4 Performance Evaluation of Teredo Relay Implementations Teredo relay handles large volume of network traffic and therefore is likely to be the bottleneck component in the Teredo mechanism. In this chapter, we investigate the performance of the three Teredo relay implementations described in the previous chapter. The output measurement is packet processing latency, which includes both packet encapsulation latency (from a public IPv6 host to a private Teredo client) and packet decapsulation latency (from a private Teredo client to a public IPv6 host).. 4.1 Measurement Environment The measurement environment consists of three hosts as illustrated in Figure 9. This environment follows the testing architecture in RFC 2544 [14] where a tester (Figure 9 (a)) is configured as both the Teredo client function and the IPv6 host. This IPv6 host runs on Redhat Linux 9 with an IPv4 UDP daemon to simulate the Teredo client function. The NAT (Figure 9 (b)) runs on Redhat Linux 9 with address mapping rules set by iptables [15]. The devices under test (DUTs) are the three Teredo relay implementations (Figure 9 (c)):. 20.
(30) NICI-Teredo (version 0.3), 6WIND-Teredo (version 1.13) and Miredo-Teredo (version 0.3.0). Both NICI-Teredo relay and Miredo-Teredo relay run on Redhat Linux 9, while 6WIND-Teredo relay runs on FreeBSD 4.9. The hardware for the Teredo relay in Figure 9 is a personal computer with 1800+ AMD Athlon CPU, 256 MB SDRAM and two RealTek 8139 100BaseTx Ethernet cards.. UDP:4096 IPv4:192.168.0.2 (IPv6:3FFE:831F:0303:0303:8000:E148:FEFE:FEFE) IPv4:192.168.0.1. IPv6:2001:4:4:4::4 NIC1. NIC2. IPv4:1.1.1.1. NIC1. NIC2. NAT (b). IPv6 host / Teredo client (a). UDP:3544 IPv4:2.2.2.2 NIC1. IPv6:2001:2:2:2::2 NIC2. Teredo relay (c). Figure 9. The test environment. In our measurement, a C program invoking pcap library [16] is used for catching the packet receiving and sending timestamps. We send one packet per second to the Teredo relay for encapsulation or decapsulation, and measure the packet processing latency. Tests are conducted with three different packet sizes (64, 512, and 1280 bytes, where the 1280-byte packet is the recommended IPv6 MTU size for Teredo [7]). Each test generates 10,000 packets to measure the encapsulation and decapsulation latencies.. 4.2 Experimental Result Figure 10 shows the 1280-byte packet encapsulation latency histograms of the three Teredo relays. The latency of the NICI-Teredo relay is clustered around 7-9µs and 12-13µs. The. 21.
(31) latency of the 6WIND-Teredo relay is around 12-16µs. The latency of the Miredo-Teredo relay is clustered around 23-26µs and 33-39µs. The 1280-byte packet decapsulation latency histograms are similar to those in Figure 10, and the average packet processing latency of the. Percentage(%). three Teredo relays are listed in Table 1.. 60. NICI-Teredo. 55. 6WIND-Teredo. 50. Miredo-Teredo. 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 10. Encapsulation latency histograms of the Teredo relays (1280 bytes). Table 1. Average processing latency Teredo relay Avg. latency of encapsulation (µs) Avg. latency of decapsulation (µs) 64 bytes. 512 bytes 1280 bytes. 64 bytes. 512 bytes 1280 bytes. NICI. 7.69. 7.82. 8.06. 8.77. 9.10. 9.24. 6WIND. 13.30. 13.53. 14.00. 14.34. 14.62. 14.80. Miredo. 23.05. 25.46. 33.08. 24.90. 33.14. 34.85. 22.
(32) 60. NICI-Teredo. 55. 6WIND-Teredo. 50. Miredo-Teredo. Percentage(%). 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 11. Encapsulation latency histograms of the Teredo relays (512 bytes). 60. NICI-Teredo. 55. 6WIND-Teredo. 50. Miredo-Teredo. Percentage(%). 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 12. Encapsulation latency histograms of the Teredo relays (64 bytes). 23.
(33) With different packet sizes (1280, 512, 64 bytes), the encapsulation latency histograms of NICI-Teredo relay and 6WIND-Teredo relay (see Figures 10, 11 and 12) have similar shapes, where the Miredo-Teredo relay has longer latency than that of the NICI-Teredo relay. The decapsulation latency histograms of the three Teredo relays can be found in Appendix A. The histograms in Appendix A shows again that NICI-Teredo relay has the best packet processing performance among the three implementations of Teredo relays. For the 1280-byte packet encapsulation latency listed in Table 1, the latency improvement of the NICI-Teredo relay over the 6WIND-Teredo relay is around 42%, and the improvement of the NICI-Teredo relay over the Miredo-Teredo relay is around 75%.. 24.
(34) Chapter 5 Conclusions This thesis addressed the NAT traversal issue between the private IPv4 and the IPv6 networks. As an NAT traversable automatic tunneling mechanism, Teredo provides convenient IPv6 access from the private IPv4 networks. We developed an efficient implementation for Teredo tunneling called NICI-Teredo. To our knowledge, NICI-Teredo is the first non-commercial Teredo implementation on Linux. Our approach has shorter packet processing latency than that of the 6WIND-Teredo relay (FreeBSD-based) and the Miredo-Teredo relay (Linux-based). The advantage of packet processing performance of the NICI-Teredo relay makes it an appropriate IPv6 tunneling solution.. As a final remark, we point out that Teredo does not work for all NAT servers. According to the rules for port mapping and access control in NAT [9], the four major types are full cone NAT, restricted cone NAT, port restricted cone NAT, and symmetric NAT. Although Teredo can successfully traverse the first three types of NATs, it fails in traversing symmetric NAT. To enhance Teredo for symmetric NAT is still an open issue for further study.. 25.
(35) Bibliography [1] R. Gilligan and E. Nordmark, “Transition Mechanisms for IPv6 Hosts and Routers”, IETF RFC 2893, Aug. 2000. [2] B. Carpenter and K. Moore, “Connection of IPv6 Domains via IPv4 Clouds”, IETF RFC 3056, Feb. 2001. [3] A. Durand, P. Fasano, I. Guardini and D. Lento, “IPv6 Tunnel Broker”, IETF RFC 3053, Jan. 2001. [4] Y.-B. Lin and I. Chlamtac, Wireless and Mobile Network Architectures. John Wiley & Sons, 2001. [5] P. Srisuresh and M. Holdrege, “IP Network Address Translator (NAT) Terminology and Considerations”, IETF RFC 2663, Aug. 1999. [6] H. Levkowetz and S. Vaarala, “Mobile IP Traversal of Network Address Translation (NAT) Devices”, IETF RFC 3519, Apr. 2003. [7] C. Huitema, “Teredo: Tunneling IPv6 over UDP through NATs”, Internet draft, draft-huitema-v6ops-teredo-05.txt (Work in Progress), Apr. 2005. [8] M. Liu, X. Wu, Y. Cai, M. Jin and D. Li, “Tunneling IPv6 with private IPv4 addresses through NAT devices”, Internet Draft, draft-liumin-v6ops-silkroad-02.txt (Work in Progress), Nov. 2004. [9] J. Rosenberg, J. Weinberger, C. Huitema and R. Mahy, “STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)”, IETF RFC 3489, Mar. 2003.. 26.
(36) [10] S.-M. Huang and Q. Wu, “Implementation of Teredo - Tunneling IPv6 through NATs”, Technical Report for National Information and Communication Initiative (NICI) IPv6 R&D Division, Taiwan, ROC, 2003. [11] Teredo for FreeBSD, http://www-rp.lip6.fr/teredo/ [12] Miredo: Teredo for Linux, http://www.simphalempin.com/dev/miredo/ [13] B. Henderson, Linux Loadable Kernel Module HOWTO, http://www.linux.org/docs/ldp/howto/Module-HOWTO/ [14] S. Bradner and J. McQuaid, “Benchmarking Methodology for Network Interconnect Devices”, IETF RFC 2544, Mar. 1999. [15] The netfilter/iptables project, http://www.netfilter.org/ [16] Tcpdump and libpcap, http://www.tcpdump.org/. 27.
(37) Appendix A Decapsulation Latency Histograms Appedix A is a supplement to the experimantal result in Chapter 4.2. This appendix shows the packet decapsulation latency histograms of the three Teredo relays (NICI-Teredo, 6WIND-Teredo and Miredo-Teredo). The 1280-byte result is showed in Figure 13, and the 512-byte and 64-byte results are showed in Figure 14 and 15,respectively.. 60. NICI-Teredo. 55. 6WIND-Teredo. 50. Miredo-Teredo. Percentage(%). 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 13. Decapsulation latency histograms of the Teredo relays (1280 bytes). 28.
(38) 60. NICI-Teredo 6WIND-Teredo Miredo-Teredo. 55 50. Percentage(%). 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 14. Decapsulation latency histograms of the Teredo relays (512 bytes). 60. NICI-Teredo. 6WIND-Teredo. 55 50. Miredo-Teredo. Percentage(%). 45 40 35 30 25 20 15 10 5 0 0. 5. 10. 15. 20. 25. 30. 35. 40. 45. 50. Delay(µs). Figure 15. Decapsulation latency histograms of the Teredo relays (64 bytes). 29.
(39) Appendix B The NICI-Teredo Server Program Appendix B lists the source code of the NICI-Teredo server. The NICI-Teredo server is implemented as a C program, which consists of a header file teredo_server.h (Appendix B.1) and a program file teredo_server.c (Appendix B.2).. B.1 teredo_server.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35. /* * Teredo Server - Tunneling IPv6 over UDP through NATs * Linux INET6 implementation * * $Id: teredo_server.h,v 1.2 2005/05/17 12:14:12 smhuang Exp $ * * File: * teredo.h - header for Teredo Server * * Version 0.0 - 12/03/03 - Initial Version. * 0.1 - 03/14/05 - Remove self-defined ipv6 structure (use ip6.h). * 0.2 - 03/17/05 - Add DEBUG_TEREDO definition. */ #ifndef _TEREDO_SERVER_H_ #define _TEREDO_SERVER_H_ const unsigned short const unsigned long const unsigned short. TEREDO_PORT = 3544; TEREDO_PREFIX = 0x3FFE831F; MAX_BUF = 2048;. struct teredo_auth { unsigned char raw_data[13]; };. struct teredo_orig { unsigned short type; unsigned short port; unsigned int addr; }; struct icmp6opt { unsigned char type; unsigned char length;. 30.
(40) 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56. unsigned char prefix_len; unsigned char flag; unsigned int valid_time; unsigned int pre_time; unsigned int reserved; unsigned int prefix[4]; }; #ifdef DEBUG_TEREDO #define DEBUG_STR(x) #define DEBUG_TRACE(x) #define DEBUG_TRACE2(n,x) #else #define DEBUG_TRACE(x) #define DEBUG_TRACE2(n,x) #endif. x printf(DEBUG_STR(x)) if ( (n) > DEBUG_LEVEL ) { printf(DEBUG_STR(x)); };. #define ERROR_TRACE(x) printk(KERN_ERR x). #endif. B.2 teredo_server.c 1 /* 2 * Teredo Server - Tunneling IPv6 over UDP through NATs 3 * Linux INET6 implementation 4 * 5 * File: 6 * teredo_server.c - Teredo Server main program 7 * 8 * Version 0.0 - 12/03/03 - Initial Version. 9 * 0.1 - 05/02/04 - Fix relay -> server bubble format. 10 * 0.2 - 08/21/04 - Fix checksum() algorithm. 11 * 0.3 - 03/14/05 - Fix bubble transmission function. 12 * 0.4 - 03/17/05 - Add packet format check. 13 */ 14 #include <stdio.h> 15 #include <sys/socket.h> 16 #include <arpa/inet.h> 17 18 #include "teredo_server.h" 19 #include "in6.h" 20 #include "ipv6.h" 21 #include <linux/icmpv6.h> 22 23 /* server address */ 24 unsigned long TEREDO_PRI_SERVER; 25 unsigned long TEREDO_SEC_SERVER; 26 27 int 28 isglobal (unsigned int addr) 29 { 30 return (addr&htonl(0xff000000) == 0 || /* the "local" subnet 0.0.0.0/8 */ 31 addr&htonl(0xff000000) == htonl(0x7f000000) || /* the "loopback" subnet 127.0.0.0/8 */ 32 addr&htonl(0xff000000) == htonl(0x0a000000) || /* the local addressing ranges 10.0.0.0/8 */ 33 addr&htonl(0xfff00000) == htonl(0xac100000) || /* the local addressing ranges 172.16.0.0/12 */ 34 addr&htonl(0xffff0000) == htonl(0xc0a80000) || /* the local addressing ranges 192.168.0.0/16 */ 35 addr&htonl(0xffff0000) == htonl(0xa9fe0000) || /* the link local block 169.254.0.0/16 */ 36 addr&htonl(0xffffff00) == htonl(0xc0586300) || /* the block reserved for 6to4 anycast. 31.
(41) addresses 192.88.99.0/24 */ 37 addr&htonl(0xf0000000) == htonl(0xe0000000) || /* the multicast address block 224.0.0.0/4 */ 38 addr == 0xffffffff)?0:1; /* the "limited broadcast" destination address 255.255.255.255 */ 39 /* TODO: the directed broadcast addresses corresponding to the subnets */ 40 } 41 42 unsigned short 43 checksum(unsigned short v6_payload_len, unsigned short v6_nexthdr, 44 struct in6_addr *v6_saddr, struct in6_addr *v6_daddr, unsigned short *data, int len) 45 { 46 unsigned short cksum = v6_payload_len + v6_nexthdr; 47 int k; 48 for (k=0; k<8; k++) 49 { 50 cksum += v6_saddr->in6_u.u6_addr16[k]; 51 cksum += (cksum < v6_saddr->in6_u.u6_addr16[k]); 52 cksum += v6_daddr->in6_u.u6_addr16[k]; 53 cksum += (cksum < v6_daddr->in6_u.u6_addr16[k]); 54 } 55 for (k=0; k<len; k++) 56 { 57 if (k == 1) 58 { 59 continue; 60 } 61 cksum += *(data+k); 62 cksum += (cksum < *(data+k)); 63 } 64 cksum ^= 0xffff; 65 66 return cksum; 67 } 68 69 70 int 71 main (int argc, char* argv[]) 72 { 73 int sockd, secfd, fd6; 74 struct sockaddr_in my_addr, my2_addr, peer_addr; 75 struct sockaddr_in6 dest; 76 const int on = 1; 77 int status, addrlen = sizeof(peer_addr), fdflag; 78 79 unsigned char recvbuf[MAX_BUF], sendbuf[MAX_BUF]; 80 81 struct teredo_orig* torig; 82 struct teredo_auth* tauth; 83 struct ipv6hdr* rv6hdr, *sv6hdr; 84 struct icmp6hdr* mp6hdr; 85 struct icmp6opt* mp6opt; 86 87 fd_set fdSet; 88 int fdSetSize; 89 90 if (argc != 3) 91 { 92 printf("Usage: %s PRI_SERVER_IPv4_ADDR SEC_SERVER_IPv4_ADDR\n", argv[0]); 93 exit(1); 94 } 95 96 /* a daemon */ 97 pid_t pid = fork(); 98 if (pid < 0) 99 {. 32.
(42) 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165. perror("fork"); exit(1); } else if (pid > 0) /* parent exit */ { exit(0); } setsid(); fclose(stdin); fclose(stdout); if (inet_pton(AF_INET, argv[1], &TEREDO_PRI_SERVER) <= 0 || inet_pton(AF_INET, argv[2], &TEREDO_SEC_SERVER) <= 0 ) { perror("inet_pton"); exit(1); } /* UDP socket for primary server */ sockd = socket(PF_INET, SOCK_DGRAM, 0); if (sockd == -1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = TEREDO_PRI_SERVER; my_addr.sin_port = htons(TEREDO_PORT); status = bind(sockd, (struct sockaddr*)&my_addr, sizeof(my_addr)); if (status == -1) { perror("bind"); exit(1); } /* UDP socket for secondary server */ secfd = socket(PF_INET, SOCK_DGRAM, 0); if (secfd == -1) { perror("socket"); exit(1); } my2_addr.sin_family = AF_INET; my2_addr.sin_addr.s_addr = TEREDO_SEC_SERVER; my2_addr.sin_port = htons(TEREDO_PORT); status = bind(secfd, (struct sockaddr*)&my2_addr, sizeof(my2_addr)); if (status == -1) { perror("bind"); exit(1); } /* IPv6 raw socket */ fd6 = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW); if (fd6 == -1) { perror("socket"); exit(1); } for (;;) { status = 0; FD_ZERO(&fdSet); FD_SET(sockd, &fdSet); FD_SET(secfd, &fdSet);. 33.
(43) 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 &addrlen); 182 183 184 185 186 187 &addrlen); 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229. if (sockd > secfd) { fdSetSize = sockd + 1; } else { fdSetSize = secfd + 1; } select(fdSetSize, &fdSet, NULL, NULL, NULL); if (FD_ISSET(sockd, &fdSet)) { fdflag = 0; status = recvfrom(sockd, recvbuf, MAX_BUF, 0, (struct sockaddr*)&peer_addr, fprintf(stderr, "recvfrom sockd: %d\n", status); } if (FD_ISSET(secfd, &fdSet)) { fdflag = 1; status = recvfrom(secfd, recvbuf, MAX_BUF, 0, (struct sockaddr*)&peer_addr, fprintf(stderr, "recvfrom secfd: %d\n", status); } /* check packet format according to the draft... */ /* 1) If the UDP content is not a well formed Teredo IPv6 packet, as defined in section 5.1.1, the packet MUST be silently discarded. */ if (status < sizeof(struct ipv6hdr)) { continue; } if (recvbuf[0] != 0x60 && recvbuf[0] != 0x00) { continue; } /* 2) If the UDP packet is not a Teredo bubble or an ICMPv6 message, it SHOULD be discarded. (The packet may be processed if the Teredo server also operates as a Teredo relay, as explained in section 5.4.) */ if (status == sizeof(struct ipv6hdr)) // bubble { rv6hdr = (struct ipv6hdr*) recvbuf; if (rv6hdr->version != 6 || rv6hdr->nexthdr != IPPROTO_NONE || rv6hdr->payload_len != 0 ) { continue; } } else if (recvbuf[0] == 0x00) { if (status < sizeof(struct teredo_orig)+sizeof(struct ipv6hdr)) { continue; } rv6hdr = (struct ipv6hdr*) &recvbuf[sizeof(struct teredo_auth)]; if (rv6hdr->nexthdr != IPPROTO_ICMPV6) { continue; } } else if (recvbuf[0] == 0x60). 34.
(44) 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295. { rv6hdr = (struct ipv6hdr*) recvbuf; if (rv6hdr->nexthdr != IPPROTO_ICMPV6) { continue; } } /* 3) If the IPv4 source address is not in the format of a global unicast address, the packet MUST be silently discarded (see section 5.2.4 for a definition of global unicast addresses). */ if (!isglobal(peer_addr.sin_addr.s_addr)) { continue; } /* If the destination IPv6 address is not a global scope IPv6 address, the packet MUST NOT be forwarded. ---see RFC 2373 */ if (rv6hdr->daddr.in6_u.u6_addr16[0]&htons(0xffc0) == htons(0xff80) || rv6hdr->daddr.in6_u.u6_addr16[0]&htons(0xffc0) == htons(0xfe80) || rv6hdr->daddr.in6_u.u6_addr16[0]&htons(0xffc0) == htons(0xfec0) ) { continue; } /* If the destination IPv6 address is a Teredo client whose address is serviced by this specific server, the server should insert an origin indication in the first bytes of the UDP payload, */ if (rv6hdr->daddr.in6_u.u6_addr32[0] == htonl(0x3ffe831f)) { if (rv6hdr->daddr.in6_u.u6_addr32[1] == TEREDO_PRI_SERVER) { if (!isglobal(rv6hdr->daddr.in6_u.u6_addr32[3])) { continue; } } else { continue; } } if (status == sizeof(struct ipv6hdr)) /* receives a bubble, relay it */ { fprintf(stderr, "source addr %x:%x\n", peer_addr.sin_addr, ntohs(peer_addr.sin_port)); /* add origin indication*/ torig = (struct teredo_orig*) sendbuf; torig->type = 0; torig->port = peer_addr.sin_port^0xffff; torig->addr = peer_addr.sin_addr.s_addr^0xffffffff; rv6hdr = (struct ipv6hdr*) recvbuf; peer_addr.sin_port = rv6hdr->daddr.in6_u.u6_addr16[5]^0xffff; peer_addr.sin_addr.s_addr = rv6hdr->daddr.in6_u.u6_addr32[3]^0xffffffff; peer_addr.sin_family = AF_INET; memcpy(&sendbuf[sizeof(struct teredo_orig)], recvbuf, sizeof(struct ipv6hdr)); if (!isglobal(peer_addr.sin_addr.s_addr)) { continue;. 35.
(45) 296 } 297 status = sendto(sockd, sendbuf, sizeof(struct teredo_orig)+sizeof(struct ipv6hdr), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 298 299 fprintf(stderr, "sendto(bubble): %d\n", status); 300 } 301 else if (status == sizeof(struct teredo_auth)+sizeof(struct ipv6hdr)+sizeof(struct icmp6hdr)+16) 302 { /* receives a router solicitation, (option size=16)*/ 303 /* add authentication indication */ 304 memcpy(sendbuf, recvbuf, sizeof(struct teredo_auth)); 305 306 /* add original indication */ 307 torig = (struct teredo_orig*) &sendbuf[sizeof(struct teredo_auth)]; 308 torig->type = 0; 309 torig->port = peer_addr.sin_port^0xffff; 310 torig->addr = peer_addr.sin_addr.s_addr^0xffffffff; 311 312 /* add IPv6 header */ 313 rv6hdr = (struct ipv6hdr*) &recvbuf[sizeof(struct teredo_auth)]; 314 sv6hdr = (struct ipv6hdr*) &sendbuf[sizeof(struct teredo_auth)+sizeof(struct teredo_orig)]; 315 sv6hdr->version = 6; 316 sv6hdr->priority = IPV6_PRIORITY_UNCHARACTERIZED; 317 sv6hdr->flow_lbl[0] = 0; sv6hdr->flow_lbl[1] = 0; sv6hdr->flow_lbl[2] = 0; 318 sv6hdr->payload_len = htons(sizeof(struct icmp6hdr)+sizeof(struct icmp6opt)+8); 319 sv6hdr->nexthdr = IPPROTO_ICMPV6; /* ICMPv6 */ 320 sv6hdr->hop_limit = 255; 321 sv6hdr->saddr.in6_u.u6_addr32[0] = htonl(0xfe800000); sv6hdr->saddr.in6_u.u6_addr32[1] = htonl(0x00000000); 322 sv6hdr->saddr.in6_u.u6_addr16[4] = htons(0x8000); 323 sv6hdr->saddr.in6_u.u6_addr16[5] = htons(TEREDO_PORT)^0xffff; 324 sv6hdr->saddr.in6_u.u6_addr32[3] = TEREDO_PRI_SERVER^0xffffffff; 325 326 sv6hdr->daddr.in6_u.u6_addr32[0] = rv6hdr->saddr.in6_u.u6_addr32[0]; 327 sv6hdr->daddr.in6_u.u6_addr32[1] = rv6hdr->saddr.in6_u.u6_addr32[1]; 328 sv6hdr->daddr.in6_u.u6_addr32[2] = rv6hdr->saddr.in6_u.u6_addr32[2]; 329 sv6hdr->daddr.in6_u.u6_addr32[3] = rv6hdr->saddr.in6_u.u6_addr32[3]; 330 //////////////// 331 /*if (sv6hdr->daddr.in6_u.u6_addr8[8] == 0x80 && fdflag == 0) 332 { 333 continue; 334 } 335 else if (fdflag == 0) 336 { 337 torig->port = htons(TEREDO_PORT)^0xffff; 338 } 339 else 340 { 341 torig->port = htons(7788)^0xffff; 342 }*/ 343 //////////////SMTEST 344 345 /* ICMPv6 header */ 346 mp6hdr = (struct icmp6hdr*) &sendbuf[sizeof(struct teredo_auth)+sizeof(struct teredo_orig)+sizeof(struct ipv6hdr)]; 347 mp6hdr->icmp6_type = 134; /* router advertisement */ 348 mp6hdr->icmp6_code = 0; 349 mp6hdr->icmp6_cksum = 0; /* calculate later */ 350 mp6hdr->icmp6_dataun.un_data32[0]= 0; 351 352 int i = sizeof(struct teredo_auth)+sizeof(struct teredo_orig)+sizeof(struct ipv6hdr)+sizeof(struct icmp6hdr); 353 sendbuf[i++] = 0x00; sendbuf[i++] = 0x00; sendbuf[i++] = 0x00; sendbuf[i++] = 0x00; 354 sendbuf[i++] = 0x00; sendbuf[i++] = 0x00; sendbuf[i++] = 0x07; sendbuf[i++] = 0xd0; 355. 36.
(46) 356 /* ICMPv6 options */ 357 mp6opt = (struct icmp6opt*) &sendbuf[i]; 358 mp6opt->type = 3; 359 mp6opt->length = 4; 360 mp6opt->prefix_len = 64; 361 mp6opt->flag = 0x40; 362 mp6opt->valid_time = 0xffffffff; 363 mp6opt->pre_time = 0xffffffff; 364 mp6opt->reserved = 0; 365 mp6opt->prefix[0] = htonl(TEREDO_PREFIX); 366 mp6opt->prefix[1] = TEREDO_PRI_SERVER; 367 mp6opt->prefix[2] = 0; 368 mp6opt->prefix[3] = 0; 369 370 mp6hdr->icmp6_cksum = checksum(sv6hdr->payload_len, htons(sv6hdr->nexthdr), 371 &(sv6hdr->saddr), &(sv6hdr->daddr), 372 (unsigned short*)&sendbuf[sizeof(struct teredo_auth)+sizeof(struct teredo_orig)+sizeof(struct ipv6hdr)], 373 (int) ntohs(sv6hdr->payload_len)/2); 374 375 if ( fdflag == 0) 376 { 377 if (sv6hdr->daddr.in6_u.u6_addr8[8] == 0x80) 378 { 379 if (!isglobal(peer_addr.sin_addr.s_addr)) 380 { 381 continue; 382 } 383 status = sendto(secfd, sendbuf, i+sizeof(struct icmp6opt), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 384 fprintf(stderr, "sendto(secfd): %d\n", status); 385 } 386 else 387 { 388 if (!isglobal(peer_addr.sin_addr.s_addr)) 389 { 390 continue; 391 } 392 status = sendto(sockd, sendbuf, i+sizeof(struct icmp6opt), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 393 fprintf(stderr, "sendto(sockd): %d\n", status); 394 } 395 } 396 else 397 { 398 if (sv6hdr->daddr.in6_u.u6_addr8[8] == 0x80) 399 { 400 if (!isglobal(peer_addr.sin_addr.s_addr)) 401 { 402 continue; 403 } 404 status = sendto(sockd, sendbuf, i+sizeof(struct icmp6opt), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 405 fprintf(stderr, "sendto(sockd): %d\n", status); 406 } 407 else 408 { 409 if (!isglobal(peer_addr.sin_addr.s_addr)) 410 { 411 continue; 412 } 413 status = sendto(secfd, sendbuf, i+sizeof(struct icmp6opt), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 414 fprintf(stderr, "sendto(secfd): %d\n", status); 415 } 416 }. 37.
(47) 417 } 418 else if (rv6hdr->saddr.in6_u.u6_addr32[0] == htonl(0x3ffe831f) && 419 rv6hdr->daddr.in6_u.u6_addr32[0] == htonl(0x3ffe831f) ) 420 { /* to another Teredo client */ 421 peer_addr.sin_port = rv6hdr->daddr.in6_u.u6_addr16[5]^0xffff; 422 peer_addr.sin_addr.s_addr = rv6hdr->daddr.in6_u.u6_addr32[3]^0xffffffff; 423 peer_addr.sin_family = AF_INET; 424 425 memcpy(&sendbuf[sizeof(struct teredo_orig)], recvbuf, sizeof(struct ipv6hdr)); 426 427 if (!isglobal(peer_addr.sin_addr.s_addr)) 428 { 429 continue; 430 } 431 status = sendto(sockd, sendbuf, sizeof(struct teredo_orig)+sizeof(struct ipv6hdr), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr)); 432 433 fprintf(stderr, "sendto(client): %d\n", status); 434 } 435 else /* receives a ping6 packet from a Teredo client */ 436 { 437 dest.sin6_family = AF_INET6; 438 dest.sin6_addr.s6_addr16[0] = 1; dest.sin6_addr.s6_addr16[1] = 1; dest.sin6_addr.s6_addr16[2] = 1; 439 dest.sin6_addr.s6_addr16[3] = 1; dest.sin6_addr.s6_addr16[4] = 1; dest.sin6_addr.s6_addr16[5] = 1; 440 dest.sin6_addr.s6_addr16[6] = 1; dest.sin6_addr.s6_addr16[7] = htons(1); 441 dest.sin6_flowinfo = 0; 442 dest.sin6_scope_id = 0; 443 dest.sin6_port = 0; 444 445 if (!isglobal(peer_addr.sin_addr.s_addr)) 446 { 447 continue; 448 } 449 status = sendto(fd6, recvbuf, status, 0, (struct sockaddr*)&dest, sizeof(dest)); 450 fprintf(stderr, "sendto6: %d\n", status); 451 } 452 } /* end for loop */ 453 454 return 0; 455 } 456. 38.
(48) Appendix C The NICI-Teredo Relay Program Appendix C lists the source code of the NICI-Teredo relay. The NICI-Teredo relay is implemented as a C program, which consists of two header files teredo.h (Appendix C.1), bubble.h (Appendix C.2) and a program file teredo.c (Appendix C.3). In teredo.h, a data structure for maintenance the tunnel reachability between the Teredo client and the Teredo relay is defined (i.e. struct teredo_peer_list). Several data structures for kernel level configuration are also defined in this file. Bubble.h definces several inline functions for handling packet tunneling. The packet encapsulation and decapsulation functions are defined in teredo.c.. C.1 teredo.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22. /* * * * * * * * * * * * * * * * * * */. Teredo tunnel device - Tunneling IPv6 over UDP through NATs Linux INET6 implementation. $Id: teredo.h,v 1.13 2005/03/10 12:50:03 smhuang Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Version 0.0 - 10/24/03 - Initial Version. 0.1 - 12/24/03 - Add Teredo Bubble support. 0.2 - 01/12/04 - Bug Fix (tunnel packet format in udpip6_tunnel_xmit). 0.3 - 03/16/04 - Add kernel thread for Bubble retransmission. 0.4 - 01/15/05 - Remove kernel thread feature. 0.5 - 03/11/05 - Add packet check feature.. #ifndef _TEREDO_H_. 39.
(49) 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88. #define _TEREDO_H_. #define __NO_VERSION__ #include <linux/kernel.h>. #define TEREDO_MTU 1280 #define TEREDO_PORT 3544 #define TEREDO_MAX_PEER #define TEREDO_QLEN 1. 0xFF. #define TEREDO_TOUT 30 /* 30 seconds */. struct teredo_peer_list { /* - The IPv6 address of the peer, - The mapped IPv4 address and mapped UDP port of the peer, - The status of the mapped address, i.e. trusted or not, - The value of the last "nonce" sent to the peer, - The date and time of the last reception from the peer, - The date and time of the last transmission to the peer, - The number of bubbles transmitted to the peer. */ struct in6_addr v6addr; u16 mapped_port; u32 mapped_addr; int status; /* turst=1, not trust=0 */ u64 nonce; struct timeval last_rx; struct timeval last_tx; int tx_bubble; //self define //limit its size --ijk-struct sk_buff_head pktq; } teredo_peer[TEREDO_MAX_PEER+1]; static int udpip6_tunnel_init(struct net_device* dev); int udpip6_rcv(struct sk_buff* skb);. static struct net_device udpip6_tunnel_dev = { name: "teredo0", init: udpip6_tunnel_init, }; static struct ip_tunnel udpip6_tunnel = { NULL, &udpip6_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"teredo0", } }; static struct inet_protocol teredo_protocol = { udpip6_rcv, 0, 0, IPPROTO_UDP,. 40.
(50) 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110. 0, NULL, "IPv6" }; static struct ip_tunnel *teredo_tunnel; static rwlock_t udpip6_lock = RW_LOCK_UNLOCKED; #ifdef DEBUG_TEREDO #define DEBUG_STR(x) #define DEBUG_TRACE(x) #define DEBUG_TRACE2(n,x) #else #define DEBUG_TRACE(x) #define DEBUG_TRACE2(n,x) #endif. KERN_DEBUG x printk(DEBUG_STR(x)) if ( (n) > DEBUG_LEVEL ) { printk x; };. #define ERROR_TRACE(x) printk(KERN_ERR x). #endif. C.2 bubble.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37. /* * * * * * * * * * * * * * * * * * */. Teredo tunnel device - Tunneling IPv6 over UDP through NATs Linux INET6 implementation. $Id: bubble.h,v 1.26 2005/03/10 12:49:36 smhuang Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Version 0.0 - 10/24/03 - Initial Version. 0.1 - 12/24/03 - Add Teredo Bubble support. 0.2 - 01/12/04 - Bug Fix (tunnel packet format in udpip6_tunnel_xmit). 0.3 - 03/16/04 - Add kernel thread for Bubble retransmission. 0.4 - 01/15/05 - Remove kernel thread feature. 0.5 - 03/11/05 - Add packet check feature.. #ifndef __BUBBLE_H_ #define __BUBBLE_H_ #include <linux/time.h> #include "teredo.h" /* **************************************************************** * returns the embedded IPv4 addr. if the IPv6 addr. * * comes from TEREDO(draft-huitema-v6ops-teredo-00) addr. space* * +-------------+-------------+-------+------+-------------+ * * | Prefix | Server IPv4 | Flags | Port | Client IPv4 | * * +-------------+-------------+-------+------+-------------+ * * - Prefix: 32 bits Teredo service prefix. * * - Server IPv4: 32 bits IPv4 addr. of a Teredo server. * * - Flags: 16 bits that document type of addr. and NAT. *. 41.
(51) 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103. * - Port: the obfuscated "mapped UDP port" of the Teredo * service at the client. * - Client IPv4: the obfuscated "mapped IPv4 address" of a * client **************************************************************** */ static inline u32 try_teredo(const struct in6_addr *v6dst) { u32 dst = 0;. * * * *. if (v6dst->s6_addr16[0] == htons(0x3ffe) && v6dst->s6_addr16[1] == htons(0x831f) ) { memcpy(&dst, &v6dst->s6_addr16[6], 4); dst = dst ^ 0xffffffff; } return dst; } static inline u16 teredo_port(const struct in6_addr *v6dst) { u16 port = 0; if (v6dst->s6_addr16[0] == htons(0x3ffe) && v6dst->s6_addr16[1] == htons(0x831f)) { memcpy(&port, &v6dst->s6_addr16[5], 2); port = port ^ 0xffff; } return port; } static inline u32 teredo_server_addr (const struct in6_addr *v6dst) { u32 dst = 0; memcpy(&dst, &v6dst->s6_addr16[2], 4); return dst; } static inline int teredo_iscone (const struct in6_addr *v6dst) { return (v6dst->s6_addr16[4] == htons(0x8000))?1:0; } static inline int teredo_isaddr (const struct in6_addr *v6dst) { return ((v6dst->s6_addr16[0] != htons(0x3ffe) || v6dst->s6_addr16[1] != htons(0x831f)))?0:1; /*if (v6dst->s6_addr16[0] != htons(0x3ffe) || v6dst->s6_addr16[1] != htons(0x831f)) { return 0; } else { return 1; }*/ } static inline u16 teredo_phash (const struct in6_addr *v6addr) { return. 42.
(52) ((v6addr->in6_u.u6_addr16[2])^(v6addr->in6_u.u6_addr16[3])^(v6addr->in6_u.u6_addr16[5])^ 104 (v6addr->in6_u.u6_addr16[6])^(v6addr->in6_u.u6_addr16[7]))&TEREDO_MAX_PEER; 105 } 106 107 static inline void 108 teredo_new_cone_peer (const struct in6_addr *v6addr) 109 { 110 u16 key = teredo_phash (v6addr); 111 teredo_peer[key].v6addr.in6_u.u6_addr32[0] = v6addr->in6_u.u6_addr32[0]; 112 teredo_peer[key].v6addr.in6_u.u6_addr32[1] = v6addr->in6_u.u6_addr32[1]; 113 teredo_peer[key].v6addr.in6_u.u6_addr32[2] = v6addr->in6_u.u6_addr32[2]; 114 teredo_peer[key].v6addr.in6_u.u6_addr32[3] = v6addr->in6_u.u6_addr32[3]; 115 116 teredo_peer[key].status = 1; 117 skb_queue_head_init(&(teredo_peer[key].pktq)); 118 return; 119 } 120 121 static inline void 122 teredo_new_peer (const struct in6_addr *v6addr) 123 { 124 u16 key = teredo_phash (v6addr); 125 teredo_peer[key].v6addr.in6_u.u6_addr32[0] = v6addr->in6_u.u6_addr32[0]; 126 teredo_peer[key].v6addr.in6_u.u6_addr32[1] = v6addr->in6_u.u6_addr32[1]; 127 teredo_peer[key].v6addr.in6_u.u6_addr32[2] = v6addr->in6_u.u6_addr32[2]; 128 teredo_peer[key].v6addr.in6_u.u6_addr32[3] = v6addr->in6_u.u6_addr32[3]; 129 130 teredo_peer[key].status = 0; 131 teredo_peer[key].tx_bubble = 0; 132 teredo_peer[key].mapped_addr = 0; 133 teredo_peer[key].mapped_port = 0; 134 skb_queue_head_init(&(teredo_peer[key].pktq)); 135 return; 136 } 137 138 static inline int 139 teredo_inc_bubble (const struct in6_addr *v6addr) 140 { 141 u16 key = teredo_phash (v6addr); 142 if (teredo_peer[key].tx_bubble <3) 143 { 144 teredo_peer[0].tx_bubble++; 145 return 0; 146 } 147 else 148 { 149 // remove the peer 150 return 1; 151 } 152 } 153 154 static inline int 155 teredo_ispeer (const struct in6_addr *v6addr) 156 { 157 u16 key = teredo_phash (v6addr); 158 if ((teredo_peer[key].v6addr.in6_u.u6_addr32[0] == v6addr->in6_u.u6_addr32[0]) && 159 (teredo_peer[key].v6addr.in6_u.u6_addr32[1] == v6addr->in6_u.u6_addr32[1]) && 160 (teredo_peer[key].v6addr.in6_u.u6_addr32[2] == v6addr->in6_u.u6_addr32[2]) && 161 (teredo_peer[key].v6addr.in6_u.u6_addr32[3] == v6addr->in6_u.u6_addr32[3]) ) 162 { 163 return 1; 164 } 165 else 166 { 167 return 0; 168 }. 43.
(53) 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234. } static inline int teredo_istrust (const struct in6_addr *v6addr) { struct timeval tv; u16 key = teredo_phash (v6addr); do_gettimeofday(&tv); if (teredo_peer[key].status == 0) { return 0; } else { //return ((tv.tv_sec- teredo_peer[key].last_tx.tv_sec) >= TEREDO_TOUT)?0:1; return 1; } } static inline void teredo_trust (const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); teredo_peer[key].status = 1; return; } static inline void teredo_add_mapped(const struct in6_addr *v6addr, const u32 addr, const u16 port) { u16 key = teredo_phash (v6addr); teredo_peer[key].mapped_addr = addr; teredo_peer[key].mapped_port = port; return; } static inline u16 teredo_peer_port(const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); return teredo_peer[key].mapped_port; } static inline u32 teredo_peer_addr(const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); return teredo_peer[key].mapped_addr; } static inline void teredo_settime_tx (const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); do_gettimeofday(&(teredo_peer[key].last_tx)); return; } static inline void teredo_settime_rx (const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); do_gettimeofday(&(teredo_peer[key].last_rx)); return;. 44.
(54) 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286. } static inline int teredo_cmptime (const struct timeval *tva, const struct timeval *tvb) { return (tva->tv_sec - tva->tv_sec); } static inline void teredo_build_bubble (struct sk_buff *skb) { struct ipv6hdr *iph6; iph6 = skb->nh.ipv6h; skb_trim(skb, sizeof(struct ipv6hdr)); iph6->priority = 0x0; iph6->version = 0x6; iph6->flow_lbl[0] = 0x0; iph6->flow_lbl[1] = 0x0; iph6->flow_lbl[2] = 0x0; iph6->payload_len = 0x0; iph6->nexthdr = IPPROTO_NONE; iph6->hop_limit = 1; return; } static inline void teredo_enqueue (const struct in6_addr *v6addr, const struct sk_buff *skb) { u16 key = teredo_phash (v6addr); skb_queue_tail(&(teredo_peer[key].pktq), (struct sk_buff *) skb); return; } static inline struct sk_buff* teredo_dequeue (const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); struct sk_buff* skb = skb_dequeue(&(teredo_peer[key].pktq)); return skb; } static inline int teredo_isqempty (const struct in6_addr *v6addr) { u16 key = teredo_phash (v6addr); return skb_queue_empty(&(teredo_peer[key].pktq)); } #endif. C.3 teredo.c 1 2 3 4 5 6. /* * Teredo tunnel device - Tunneling IPv6 over UDP through NATs * Linux INET6 implementation * * * $Id: teredo.c,v 1.33 2005/03/10 12:49:56 smhuang Exp $. 45.
(55) 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72. * * * * * * * * * * * * * * */. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Reference: net/ipv6/sit.c Version 0.0 - 10/24/03 - Initial Version. 0.1 - 12/24/03 - Add Teredo Bubble support. 0.2 - 01/12/04 - Bug Fix (tunnel packet format in udpip6_tunnel_xmit). 0.3 - 03/16/04 - Add kernel thread for Bubble retransmission. 0.4 - 01/15/05 - Remove kernel thread feature. 0.5 - 03/11/05 - Add packet check feature.. #include <linux/module.h> #include <asm/uaccess.h> #include <linux/netfilter_ipv4.h> #include <net/ipv6.h> #include <net/protocol.h> #include <net/ip6_route.h> #include <net/ndisc.h> #include <net/addrconf.h> #include <net/ip.h> #include <net/udp.h> #include <net/icmp.h> #include <net/ipip.h> #include <net/inet_ecn.h> #include "teredo.h" #include "bubble.h". /* **************************************************************** * Decapsulates the IPv4 and UDP headers of skb to IPv6 * 1) check validity * 2) add an entry in teredo peer list if receives a bubble * 3) remove the IPv4 and UDP header * 4) call netif_rx() for delivery to a normal IPv6 host **************************************************************** */ int udpip6_rcv(struct sk_buff *skb) { struct iphdr *iph; struct udphdr *uh; struct ipv6hdr *iph6; struct ip_tunnel *tunnel; DEBUG_TRACE("TEREDO:udpip6_rcv\n"); if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { goto out; } iph = skb->nh.iph; read_lock(&udpip6_lock); if(skb->h.uh!=NULL) { uh = skb->h.uh;. 46. * * * * *.
相關文件
However, NTP SIPv6 UA cannot communicate with CISCO PSTN gateway, and CCL PCA (IPv6 SIP UA) cannot communicate with CISCO PSTN gateway and Pingtel hardware-based SIP phone.
A host connecting to the outside network is allocated an external IP address from the address pool managed by NAT... Flavors of
• A function is a piece of program code that accepts input arguments from the caller, and then returns output arguments to the caller.. • In MATLAB, the syntax of functions is
Object decoration (for example bottle, hat, parcel/packet, car,etc) (十四) 花籃 Flower basket. (十五) 胸花
• Instead of uploading and downloading the dat a from cloud to client for computing , we shou ld directly computing on the cloud ( public syst em ) to save data transferring time.
The development of IPv6 was to a large extent motivated by the concern that we are running out of 4-byte IPv4 address space.. And indeed we are: projections in- dicate that the
Object decoration (for example bottle, hat, parcel/packet, car,etc) (十四) 花籃 Flower basket. (十五)
Remote root compromise Web server defacement Guessing/cracking passwords Copying databases containing credit card numbers Viewing sensitive data without authorization Running a