In this Document
Goal
Solution
Background
Configuring a Linux Database and Client for the IPv4 Mapped Address
Configure Linux
Configure the Database Listener
Configuring the Client
Test the Connection
Other methods to validate that IPv6 is being used
APPLIES TO:
Oracle Server - Enterprise Edition - Version: 11.2.0.0 to 11.2.0.0
Oracle Net Services - Version: 11.2.0.0 to 11.2.0.0
Information in this document applies to any platform.
GOAL
During the conversion to IPv6 there is a specific address range that has been allocated for use during specific migration conditions. This address range is for IPv4 Mapping. This IPv6 address allows an application that only knows IPv6 to be able to communicate with an application that only understands IPv4. This address range has the form of “::FFFF:{IPv4 address}”.
SOLUTION
Background
The designers of IPv6 have allocated specific address ranges for certain purposes. This article covers how to configured the Oracle database and client to use the IPv4 Mapping Address. The IPv4 Mapping Address is not an IPv6 tunnel, but is a configuration of the Operating System to allow an IPv6 application to use the IPv4 protocol.
These IPv6 addresses have a specific format. According to RFC 4191, the IPv4-Mapped IPv6 Address has the first eighty bits are zeros. The next 16 bits (2 octets) are all ones. The last 32 bits are the IPv4 address in either the IPv4 dot notation or the Hexadecimal equivalent. In the example below, each address is equivalent:
0000:0000:0000:0000:0000:FFFF:129.168.134.145
0000:0000:0000:0000:0000:FFFF:81A8:8691
::FFFF: 129.168.134.145
::FFFF: 81A8:8691
The leading zeros, coupled with the 16 bits of ones, flag this to be an IPv4 Mapped address.
The translation of the IPv4 packets into an IPv6 compatible format is performed by the Operating System. Because of this, the Operating System should be run in a dual-stack configuration. Configuring a system to use nothing but IPv6, in essence, removes all the code needed for it to understand the IPv4 protocol format. The existing implementations that Operating Systems are using require both protocol stacks installed and functioning.
The purpose for the IPv6 address range is to handle the condition where an application has been written to use only IPv6. The Oracle database and client have been written to only use both IPv4 and IPv6. Because of this multiple protocol support, there may be no reason to use the IPv4 Mapping feature for Oracle. However, if this is feature is needed, this paper covers how to configure it.
Configuring a Linux Database and Client for the IPv4 Mapped Address
The first step is to make sure the Operating System has IPv6 configured. There are many other documents that cover this step, so it does not need to be covered here.
Configure Linux
To configure Linux with this specific IPv6 address, you modify the /etc/sysconfig/network-scripts/ifcfg-{device name} file. In my case I modified the ifcfg-eth0 file. I had previously added an IPv6 address and will add a secondary IPv6 address for the IPv4 Mapped Address.
DEVICE=eth0
BOOTPROTO=none
HWADDR=00:21:91:19:71:60
ONBOOT=yes
TYPE=Ethernet
NETMASK=255.255.255.0
IPADDR=192.168.144.162
GATEWAY=192.168.144.1
USERCTL=no
PEERDNS=yes
IPV6INIT=yes
IPV6ADDR=2001:c00:1234:1234::1/64
IPV6ADDR_SECONDARIES=::ffff:192.168.144.162/64
Once these files have been configured, run the command “service network reload” to have the OS reinitialize the network with the changes made. To validate these changes, issue the command “/sbin/ifconfig eth0”. The results of the ifconfig command should look similar to:
eth0 Link encap:Ethernet HWaddr 00:21:91:19:71:60
inet addr:192.168.144.162 Bcast:192.168.144.255 Mask:255.255.255.0
inet6 addr: fe80::221:91ff:fe19:7160/64 Scope:Link
inet6 addr: 2001:c00:1234:1234::1/64 Scope:Global
inet6 addr: ::ffff:192.168.144.162/64 Scope:Global
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:206503 errors:0 dropped:0 overruns:0 frame:0
TX packets:12815 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:14508086 (13.8 MiB) TX bytes:11560730 (11.0 MiB)
Interrupt:169
Configure the Database Listener
The next step is to configure the Listener for this IPv6 address. Here is an example of the LISTENER.ORA file:
# listener.ora Network Configuration File: /home/oracle/app/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora
# Generated by Oracle configuration tools.
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = ::ffff:192.168.144.162)(PORT = 1521)(IP=FIRST))
)
)
In this example, I’ve only used the IPv6 address. If you decide to have the IPv4 address also, the two addresses will have to have different port numbers. At this time, Linux requires different port numbers to be used even though these are separate IP addresses.
Once the Listener is properly configured it will have this status:
$ lsnrctl status
LSNRCTL for Linux: Version 11.2.0.0.2 - Beta on 22-MAY-2009 04:13:12
Copyright (c) 1991, 2009, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 11.2.0.0.2 - Beta
Start Date 22-MAY-2009 04:08:03
Uptime 0 days 0 hr. 5 min. 9 sec
Trace Level support
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /home/oracle/app/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora
Listener Log File /home/oracle/app/oracle/diag/tnslsnr/coerac1/listener/alert/log.xml
Listener Trace File /home/oracle/app/oracle/diag/tnslsnr/coerac1/listener/trace/ora_19171_47932120142624.trc
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.144.162)(PORT=1521)))
Services Summary...
Service "V11R21.us.oracle.com" has 1 instance(s).
Instance "V11R21", status READY, has 1 handler(s) for this service...
Service "V11R21XDB.us.oracle.com" has 1 instance(s).
Instance "V11R21", status READY, has 1 handler(s) for this service...
The command completed successfully
Note: Even though we configured the Listener to use an IPv6 address, that the OS has mapped the address back into an IPv4 address.
Enabling Listener tracing, we see the Listener process ask to use the IPv6 address, but later the address is actually resolved by the OS to the IPv4 address:
2009-05-22 04:15:24.241618 : nslisten:entry
2009-05-22 04:15:24.241644 : nsc2addr:entry
2009-05-22 04:15:24.241658 : nsc2addr:(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=::ffff:192.168.144.162)(PORT=1521)(IP=FIRST)))
2009-05-22 04:15:24.241688 : nttbnd2addr:entry
2009-05-22 04:15:24.241709 : nttbnd2addr:ip=first specified - listen on 1st ip addr
2009-05-22 04:15:24.241725 : snlinGetAddrInfo:entry
2009-05-22 04:15:24.241743 : snlinGetAddrInfo:exit
2009-05-22 04:15:24.241758 : nttbnd2addr:using host IP address: ::ffff:192.168.144.162
2009-05-22 04:15:24.241775 : snlinFreeAddrInfo:entry
2009-05-22 04:15:24.241789 : snlinFreeAddrInfo:exit
2009-05-22 04:15:24.241802 : nttbnd2addr:exit
2009-05-22 04:15:24.241816 : nsc2addr:normal exit
…
2009-05-22 04:15:24.242206 : nsopen:opening transport...
2009-05-22 04:15:24.242220 : nttcon:entry
2009-05-22 04:15:24.242233 : nttcon:toc = 2
2009-05-22 04:15:24.242247 : nttcnp:entry
2009-05-22 04:15:24.242261 : ntvlin:entry
2009-05-22 04:15:24.242275 : ntvllt:entry
2009-05-22 04:15:24.242290 : ntvllt:tcp.validnode_checking not turned on
2009-05-22 04:15:24.242317 : ntvllt:exit
2009-05-22 04:15:24.242330 : ntvlin:exit
2009-05-22 04:15:24.242344 : nttcnp:Validnode Table IN use; err 0x0
2009-05-22 04:15:24.242357 : nttcnp:creating a socket.
2009-05-22 04:15:24.242385 : nttcnp:binding an address to a socket.
2009-05-22 04:15:24.242405 : nttcnp:listening on a bound socket (queue size = 128).
2009-05-22 04:15:24.242434 : nttcnp:getting sockname
2009-05-22 04:15:24.242452 : nttcnp:getting peername
2009-05-22 04:15:24.242466 : nttcnp:exit
2009-05-22 04:15:24.242485 : nttcon:exit
2009-05-22 04:15:24.242501 : nsopen:transport is open
…
2009-05-22 04:15:24.242680 : nsopen:normal exit
2009-05-22 04:15:24.242693 : nslisten:normal exit
2009-05-22 04:15:24.242706 : nsgllsn:completing partial addr: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=::ffff:192.168.144.162)(PORT=1521)(IP=FIRST)))
2009-05-22 04:15:24.242726 : nttaddr2bnd:entry
2009-05-22 04:15:24.242742 : snlinGetNameInfo:entry
2009-05-22 04:15:24.242764 : snlinGetNameInfo:exit
2009-05-22 04:15:24.242778 : nttaddr2bnd:Resolved to 192.168.144.162
2009-05-22 04:15:24.242794 : nttaddr2bnd:exit
2009-05-22 04:15:24.242904 : nsgllsn:Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.144.162)(PORT=1521)))
Configuring the Client
The client should use the IPv4 address. Since the purpose behind this special IPv6 address is to allow an application that can only use IPv6 to be able to converse with an application that can only use IPv4, we will configure the client to use IPv4. TNSNAMES.ORA file uses an IPv4 address:
V11R21-FFFF =
(DESCRIPTION = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = coerac1.us.oracle.com)(PORT = 1521)))
(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = V11R21.us.oracle.com)))
Test the Connection
The first test is to use the utility TNSPING. Here we test from a Windows OS based client that is running Oracle version 11.1.0.7. Since this is a client that only uses IPv4, it is OK to use an earlier version of Oracle.
C:\>tnsping V11R21-FFFF
TNS Ping Utility for 32-bit Windows: Version 11.1.0.7.0 - Production on 22-MAY-2009 11:30:14
Copyright (c) 1997, 2008, Oracle. All rights reserved.
Used parameter files:
D:\Oracle\Product\11.1.0\db_1\network\admin\sqlnet.ora
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = coerac1.us.oracle.com)(PORT = 1521))) (CO
NNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = V11R21.us.oracle.com)))
OK (40 msec)
The Listener is up on the host coerac1 and listening on port 1521.
Once a client finishes contacting the Listener, it gets handed off to a Server process. To test the final connection is working, we use SQL*Plus:
C:\ >sqlplus scott/tiger@v11r21-ffff
SQL*Plus: Release 11.1.0.7.0 - Production on Fri May 22 11:34:06 2009
Copyright (c) 1982, 2008, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.0.2 - 64bit Beta
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL>
Other methods to validate that IPv6 is being used
Other utilities can be used to validate that IPv6 is being used. The most common for Unix are lsof and strace (strace is similar to truss on other Operating Systems).
lsof
The Unix utility lsof (LiSt Of Files) will show which IP sockets are being used. In this example both IPv4 and IPv6 sockets are being used. The IPv4 socket being used is the loopback address, while the IPv6 seems to have the IPv4 address listed but with the IPv6 protocol family.
$ lsof -n -P -R -Tqs -U -p 19724 | grep IPv4
tnslsnr 19724 1 oracle 13u IPv4 85616 TCP 127.0.0.1:27745->127.0.0.1:6150 (ESTABLISHED QR=0 QS=0)
$ lsof -n -P -R -Tqs -U -p 19724 | grep IPv6
tnslsnr 19724 1 oracle 11u IPv6 85606 TCP 192.168.144.162:1521 (LISTEN QR=0 QS=0)
tnslsnr 19724 1 oracle 14u IPv6 85624 TCP 192.168.144.162:1521->192.168.144.162:47690 (ESTABLISHED QR=0 QS=0)
strace
The strace command syntax used for this example was:
strace -f -r -tt -T -v -x –o outfile.out lsnrctl start
The following strace output was generated when a Windows client used TNSPING to connect to the Listener. The first number in the file output below is the line number shown when using the utility vi to examine the file.
Line 1641 is when the Listener was woken up from its poll on the file descriptor 11 (fd=11), which is the socket it is listening on.
Line 1643 is getting the socket name for file descriptor 11, we see that it is an IPv6 socket as the AF_INET6 protocol family and the IPv6 address are listed.
Line 1645 is where the connection gets accepted, and the next line shows that it too is an IPv6 file (the file descriptor created is now 14).
Line 1656 is the Listener reading an inbound packet on file descriptor 14, which is a connect packet containing the TNSPING command
Line 1660 is a write to file descriptor 14, which is the Listener’s response, all on the IPv6 socket.
1641 19595 5.061708 <... poll resumed> ) = 1 ([{fd=11, revents=POLLIN|POLLRDNORM}]) <5 .062422="">
1642 19595 0.000114 times({tms_utime=1, tms_stime=1, tms_cutime=0, tms_cstime=0}) = 445918642 <0 .000007="">
1643 19595 0.000057 getsockname(11, {sa_family=AF_INET6, sin6_port=htons(1521), inet_pton(AF_INET6, "::ffff:192.168.144.162", &s in6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [10492268258432909340]) = 0 <0 .000007="">
1644 19595 0.000061 getpeername(11, 0x7fff19db01c8, [10492268258432909340]) = -1 ENOTCONN (Transport endpoint is not connected) <0 .000021="">
1645 19595 0.000061 accept(11, {sa_family=AF_INET6, sin6_port=htons(3570), inet_pton(AF_INET6, "::ffff:192.168.144.158", &sin6_a ddr), sin6_flowinfo=0, sin6_scope_id=0}, [120259084316]) = 14 <0 .000017="">
1646 19595 0.000065 getsockname(14, {sa_family=AF_INET6, sin6_port=htons(1521), inet_pton(AF_INET6, "::ffff:192.168.144.162", &s in6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [120259084316]) = 0 <0 .000007="">
1647 19595 0.000065 fcntl(14, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 <0 .000007="">
1648 19595 0.000035 getsockopt(14, SOL_SOCKET, SO_SNDBUF, [1863088643283894272], [4]) = 0 <0 .000007="">
1649 19595 0.000038 getsockopt(14, SOL_SOCKET, SO_RCVBUF, [1863088643283965268], [4]) = 0 <0 .000006="">
1650 19595 0.000040 setsockopt(14, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0 .000007="">
1651 19595 0.000036 fcntl(14, F_SETFD, FD_CLOEXEC) = 0 <0 .000007="">
1652 19595 0.000031 times({tms_utime=1, tms_stime=1, tms_cutime=0, tms_cstime=0}) = 445918642 <0 .000007="">
1653 19595 0.000089 rt_sigaction(SIGPIPE, {SIG_IGN, ~[ILL ABRT BUS FPE SEGV USR2 XCPU XFSZ SYS RTMIN RT_1], SA_RESTORER|SA_REST ART|SA_SIGINFO, 0x3833a0e4c0}, {SIG_IGN, ~[ILL ABRT BUS FPE KILL SEGV USR2 STOP XCPU XFSZ SYS RTMIN RT_1], SA_RESTORER|SA_RESTA RT|SA_SIGINFO, 0x3833a0e4c0}, 8) = 0 <0 .000008="">
1654 19595 0.000072 times({tms_utime=1, tms_stime=1, tms_cutime=0, tms_cstime=0}) = 445918642 <0 .000006="">
1655 19595 0.000037 poll([{fd=8, events=POLLIN|POLLRDNORM}, {fd=11, events=POLLIN|POLLRDNORM}, {fd=12, events=POLLIN|POLLRDNORM }, {fd=14, events=POLLIN|POLLRDNORM}], 4, 60000) = 1 ([{fd=14, revents=POLLIN|POLLRDNORM}]) <0 .000008="">
1656 19595 0.000065 read(14, "\x00\x57\x00\x00\x01\x00\x00\x00\x01\x3a\x01\x2c\x00\x00\x20\x00\x7f\xff\xc6\x0e\x00\x00\x01\x00\ x00\x1d\x00\x3a\x00\x00\x00\x00"..., 8208) = 87 <0 .000010="">
1657 19595 0.000079 fcntl(14, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK) <0 .000006="">
1658 19595 0.000034 fcntl(14, F_SETFL, O_RDWR) = 0 <0 .000006="">
1659 19595 0.000029 times({tms_utime=1, tms_stime=1, tms_cutime=0, tms_cstime=0}) = 445918642 <0 .000006="">
1660 19595 0.000087 write(14, "\x00\x49\x00\x00\x04\x00\x00\x00\x22\x00\x00\x3d\x28\x44\x45\x53\x43\x52\x49\x50\x54\x49\x4f\x4e \x3d\x28\x54\x4d\x50\x3d\x29\x28"..., 73) = 73 <0 .000015="">
1661 19595 0.000064 setsockopt(14, SOL_SOCKET, SO_SNDTIMEO, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) = 0 <0 .000008="">
1662 19595 0.000041 setsockopt(14, SOL_SOCKET, SO_RCVTIMEO, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) = 0 <0 .000007="">
1663 19595 0.000045 close(14) = 0 <0 .000021="">0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>0>5>
No hay comentarios:
Publicar un comentario
Te agradezco tus comentarios. Te esperamos de vuelta.