UTL_INADDR包獲取ip地址的內部原理

聽海★藍心夢發表於2013-12-25

我們知道,透過SYS_CONTEXT函式可以獲得這部分資訊,當前使用者的ip等資訊可以透過如下命令輕易獲取:

SQL> select sys_context('userenv','host') from dual;

SYS_CONTEXT('USERENV','HOST')
--------------------------------------------------------------------------------
WORKGROUP\GQGAI

SQL> select sys_context('userenv','ip_address') from dual;

SYS_CONTEXT('USERENV','IP_ADDR
--------------------------------------------------------------------------------
172.16.34.20


可是如果我們希望獲取其它session的地址資訊等,透過SYS_CONTEXT函式就只能透過LOGON觸發器來完成。

而如果沒有觸發器記錄,則我們可以透過UTL_INADDR Package來實現。
我們看一下UTL_INADDR包獲取ip等資訊的實現原理。

我們在資料庫中進行如下查詢:

[oracle@jumper oracle]$ sqlplus "/ as sysdba"


SQL*Plus: Release 9.2.0.4.0 - Production on Wed Oct 25 11:24:22 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning option
JServer Release 9.2.0.4.0 - Production

SQL> !
[oracle@jumper oracle]$ ps -ef|grep sql
oracle 14700 14663 1 11:24 pts/0 00:00:00 sqlplus
oracle 14732 14702 0 11:24 pts/0 00:00:00 grep sql
[oracle@jumper oracle]$ ps -ef|grep LO
oracle 14701 14700 0 11:24 ? 00:00:00 oracleeygle (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle 14734 14702 0 11:24 pts/0 00:00:00 grep LO
[oracle@jumper oracle]$ exit
exit

SQL> SELECT UTL_INADDR.get_host_address('') from dual;

UTL_INADDR.GET_HOST_ADDRESS('')
---------------------------------------------------------------------
208.113.151.109


在Linux中我們透過strace跟蹤這個程式,可以得到以下堆疊資訊:

[oracle@jumper oracle]$ strace -p 14701
Process 14701 attached - interrupt to quit
read(7, "\0\313\0\0\6\0\0\0\0\0\3^\10a\200\0\0\0\0\0\0@\342\22\10"..., 2064) = 203
gettimeofday({1161746697, 269895}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 30000}, ru_stime={0, 10000}, ...}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
gettimeofday({1161746697, 270542}, NULL) = 0
gettimeofday({1161746697, 270670}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
gettimeofday({1161746697, 271614}, NULL) = 0
gettimeofday({1161746697, 271748}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
gettimeofday({1161746697, 272347}, NULL) = 0
gettimeofday({1161746697, 272699}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
gettimeofday({1161746697, 272989}, NULL) = 0
gettimeofday({1161746697, 273140}, NULL) = 0
gettimeofday({1161746697, 273273}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 10000}, ...}) = 0
gettimeofday({1161746697, 273771}, NULL) = 0
gettimeofday({1161746697, 275526}, NULL) = 0
getpid() = 14701
open("/etc/resolv.conf", O_RDONLY) = 12
fstat64(12, {st_mode=S_IFREG|0644, st_size=46, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fba000
read(12, "search hurray.com.cn\nnameserver "..., 4096) = 46
read(12, "", 4096) = 0
close(12) = 0
munmap(0xb6fba000, 4096) = 0
socket(PF_UNIX, SOCK_STREAM, 0) = 12
connect(12, {sa_family=AF_UNIX, path="/var/run/.nscd_socket"}, 110) = -1 ENOENT (No such file or directory)
close(12) = 0
open("/etc/host.conf", O_RDONLY) = 12
fstat64(12, {st_mode=S_IFREG|0644, st_size=17, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fba000
read(12, "order hosts,bind\n", 4096) = 17
read(12, "", 4096) = 0
close(12) = 0
munmap(0xb6fba000, 4096) = 0
futex(0xb71a1a20, FUTEX_WAKE, 2147483647) = 0
open("/etc/hosts", O_RDONLY) = 12
fcntl64(12, F_GETFD) = 0
fcntl64(12, F_SETFD, FD_CLOEXEC) = 0
fstat64(12, {st_mode=S_IFREG|0644, st_size=175, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6fba000
read(12, "# Do not remove the following li"..., 4096) = 175
read(12, "", 4096) = 0
close(12) = 0
munmap(0xb6fba000, 4096) = 0
open("/opt/oracle/product/9.2.0/lib/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/tls/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/i686/libnss_dns.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libnss_dns.so.2", O_RDONLY) = 12
read(12, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\16"..., 512) = 512
fstat64(12, {st_mode=S_IFREG|0755, st_size=18632, ...}) = 0
old_mmap(NULL, 17100, PROT_READ|PROT_EXEC, MAP_PRIVATE, 12, 0) = 0xb6fb6000
old_mmap(0xb6fba000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 12, 0x3000) = 0xb6fba000
close(12) = 0
open("/opt/oracle/product/9.2.0/lib/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/tls/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/i686/libresolv.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libresolv.so.2", O_RDONLY) = 12
read(12, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\320(\0"..., 512) = 512
fstat64(12, {st_mode=S_IFREG|0755, st_size=76508, ...}) = 0
old_mmap(NULL, 73604, PROT_READ|PROT_EXEC, MAP_PRIVATE, 12, 0) = 0xb6fa4000
old_mmap(0xb6fb3000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 12, 0xf000) = 0xb6fb3000
old_mmap(0xb6fb4000, 8068, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb6fb4000
close(12) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 12
connect(12, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("208.113.151.109")}, 28) = 0
send(12, "\324#\1\0\0\1\0\0\0\0\0\0\3www\5anysql\3com\0\0\1\0\1", 31, 0) = 31
gettimeofday({1161746697, 286025}, NULL) = 0
poll([{fd=12, events=POLLIN, revents=POLLIN}], 1, 5000) = 1
ioctl(12, FIONREAD, [74]) = 0
recvfrom(12, "\324#\201\200\0\1\0\1\0\1\0\0\3www\5anysql\3com\0\0\1\0"..., 1024, 0,
{sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("208.113.151.109")}, [16]) = 74
close(12) = 0
gettimeofday({1161746697, 290245}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 20000}, ...}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 20000}, ...}) = 0
gettimeofday({1161746697, 291553}, NULL) = 0
write(10, "\2\275\0\0\6\0\0\0\0\0\20\31\266\344\217\3700\320\341S"..., 701) = 701
read(7, "\0\215\0\0\6\0\0\0\0\0\3^\t@\0\0\0\1\0\0\0\0\0\0\0\0\0"..., 2064) = 141
gettimeofday({1161746697, 294898}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 20000}, ...}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 20000}, ...}) = 0
gettimeofday({1161746697, 295496}, NULL) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 40000}, ru_stime={0, 20000}, ...}) = 0
gettimeofday({1161746697, 295847}, NULL) = 0
gettimeofday({1161746697, 295981}, NULL) = 0
lseek(9, 1024, SEEK_SET) = 1024
read(9, "\30\0$\0007\0@\0J\0V\0`\0i\0t\0~\0\232\0\245\0\320\0\330"..., 512) = 512
lseek(9, 47104, SEEK_SET) = 47104
read(9, "\f\0^\5\0\0P\0x\5\0\0\214\0y\5\0\0\250\0z\5\0\0\313\0{"..., 512) = 512
gettimeofday({1161746697, 297024}, NULL) = 0
write(10, "\0\202\0\0\6\0\0\0\0\0\4\1\0\0\0\1\1\0\0\0{\5\0\0\0\0\1"..., 130) = 130
read(7,
Process 14701 detached


在這個資訊中,我們注意到Oracle順序訪問了如下檔案來完成地址定位:

open("/etc/resolv.conf", O_RDONLY) = 12
open("/etc/host.conf", O_RDONLY) = 12
open("/etc/hosts", O_RDONLY) = 12


首先獲取域名解析伺服器,在根據host.conf檔案確定解析順序,因為預設hosts檔案優先,又繼續讀取/etc/hosts檔案。

如果hosts檔案存在解析關係,則返回資訊;如果不存在,則繼續問詢DNS伺服器,獲得解析地址,如果不能解析,則會出錯:

SQL> select UTL_INADDR.get_host_address('') from dual;
select UTL_INADDR.get_host_address('') from dual
*
ERROR at line 1:
ORA-29257: host unknown
ORA-06512: at "SYS.UTL_INADDR", line 35
ORA-06512: at "SYS.UTL_INADDR", line 40
ORA-06512: at line 1

也就是說,UTL_INADDR的資料獲取已經不依賴於資料庫資訊了,而SYS_CONTEXT的資訊獲取仍然來自資料庫內部。


這就是UTL_INADDR包的工作原理。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/751371/viewspace-1064213/,如需轉載,請註明出處,否則將追究法律責任。

相關文章