2021-04-26 20:07:00 +02:00
|
|
|
#coding:utf-8
|
|
|
|
|
2022-01-25 22:55:48 +01:00
|
|
|
"""
|
|
|
|
ID: issue-5508
|
2024-06-13 09:13:02 +02:00
|
|
|
ISSUE: https://github.com/FirebirdSQL/firebird/issues/5508
|
2022-01-25 22:55:48 +01:00
|
|
|
TITLE: Allow to enforce IPv4 or IPv6 in URL-like connection strings
|
|
|
|
DESCRIPTION:
|
|
|
|
JIRA: CORE-5229
|
2022-02-02 15:46:19 +01:00
|
|
|
FBTEST: bugs.core_5229
|
2024-06-13 09:13:02 +02:00
|
|
|
NOTES:
|
|
|
|
[04.02.2022] pcisar
|
|
|
|
Test may fail with IPv6.
|
|
|
|
For example it fails on my Linux OpenSuSE Tumbleweed with regular setup (IPv6 should not be disabled).
|
|
|
|
Test should IMHO check IPv4/IPv6 availability on test host before runs inet6:// check.
|
|
|
|
[13.06.2024] pzotov
|
|
|
|
1. Added check for ability to use IPv6.
|
2024-06-14 10:09:48 +02:00
|
|
|
2. Attempt to specify explicitly IPv6 address "[::1]" in ES/EDS caused error:
|
2024-06-13 09:13:02 +02:00
|
|
|
========
|
|
|
|
Statement failed, SQLSTATE = 42000
|
|
|
|
External Data Source provider 'inet6://[' not found
|
|
|
|
========
|
2024-06-14 10:09:48 +02:00
|
|
|
It was fixed in gh-8156.
|
2024-08-26 22:46:15 +02:00
|
|
|
3. On Windows there is no way to make IPv6 'fully disabled': address '::1' remains active.
|
|
|
|
According to https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows
|
|
|
|
"You cannot completely disable IPv6 as IPv6 is used internally on the system for many TCPIP tasks.
|
|
|
|
For example, you will still be able to run ping ::1 after configuring this setting"
|
|
|
|
|
|
|
|
We can turn off listening of '::1' by FB server if do following:
|
|
|
|
* run PowerShell and type there: Enable-NetAdapterBinding -Name "*" -ComponentID ms_tcpip6
|
|
|
|
* chcp 65001, then: ipconfig /all | findstr /i /r /c:" IPv6.*(preferred)"
|
|
|
|
* save somewhere IPv6 address from previous command (e.g. 'fe80::f53c:9ecf:aad:4761%14')
|
|
|
|
* change in firebird.conf: RemoteBindAddress = fe80::f53c:9ecf:aad:4761
|
|
|
|
But this requires RESTART of FB server thus cannot be used in QA.
|
|
|
|
Discussed with Vlad 13-jun-2024.
|
2024-06-14 10:09:48 +02:00
|
|
|
[14.06.2024] pzotov
|
|
|
|
Checked "on external 'inet6://[::1]/{act.db.db_path}'" after fixed GH-8156, builds:
|
|
|
|
3.0.12.33757, 4.0.5.3112, 5.0.1.1416, 6.0.0.374
|
2024-06-13 09:13:02 +02:00
|
|
|
"""
|
2022-01-25 22:55:48 +01:00
|
|
|
import pytest
|
|
|
|
from firebird.qa import *
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-01-25 22:55:48 +01:00
|
|
|
db = db_factory()
|
2021-12-06 19:23:35 +01:00
|
|
|
|
2022-01-25 22:55:48 +01:00
|
|
|
act = python_act('db')
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2024-06-13 09:13:02 +02:00
|
|
|
#------------------------------------------
|
|
|
|
# https://stackoverflow.com/questions/66246308/detect-if-ipv6-is-supported-os-agnostic-no-external-program/66249915#66249915
|
|
|
|
# https://stackoverflow.com/a/66249915
|
|
|
|
|
|
|
|
def check_ipv6_avail():
|
|
|
|
import socket
|
|
|
|
import errno
|
|
|
|
|
|
|
|
# On Windows, the E* constants will use the WSAE* values
|
|
|
|
# So no need to hardcode an opaque integer in the sets.
|
|
|
|
_ADDR_NOT_AVAIL = {errno.EADDRNOTAVAIL, errno.EAFNOSUPPORT}
|
|
|
|
_ADDR_IN_USE = {errno.EADDRINUSE}
|
|
|
|
|
|
|
|
res = -1
|
|
|
|
if not socket.has_ipv6:
|
|
|
|
# If the socket library has no support for IPv6, then the
|
|
|
|
# question is moot as we can't use IPv6 anyways.
|
|
|
|
return res
|
|
|
|
|
|
|
|
sock = None
|
|
|
|
try:
|
|
|
|
#with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as sock:
|
|
|
|
# sock.bind(("::1", 0))
|
|
|
|
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
|
|
|
sock.bind(("::1", 0))
|
|
|
|
#sock.shutdown(socket.SHUT_RDWR) # [Errno 107] Transport endpoint is not connected
|
|
|
|
sock.close()
|
|
|
|
res = 0
|
|
|
|
except socket.error as x:
|
|
|
|
# sysctl net.ipv6.conf.all.disable_ipv6=1
|
|
|
|
# sysctl net.ipv6.conf.default.disable_ipv6=1
|
|
|
|
# sock.bind(("::1", 0)) --> socket.error: [Errno 99] Cannot assign requested address
|
|
|
|
#print(x)
|
|
|
|
res = -2
|
|
|
|
except OSError as e:
|
|
|
|
if e.errno in _ADDR_NOT_AVAIL:
|
|
|
|
res = -3
|
|
|
|
elif e.errno in _ADDR_IN_USE:
|
|
|
|
# This point shouldn't ever be reached. But just in case...
|
|
|
|
res = -4
|
|
|
|
else:
|
|
|
|
# Other errors should be inspected
|
|
|
|
res = -5
|
|
|
|
|
|
|
|
return res
|
|
|
|
#------------------------------------------
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2024-06-09 17:53:05 +02:00
|
|
|
@pytest.mark.es_eds
|
2021-04-26 20:07:00 +02:00
|
|
|
@pytest.mark.version('>=3.0.1')
|
2022-01-25 22:55:48 +01:00
|
|
|
def test_1(act: Action):
|
2024-06-13 09:13:02 +02:00
|
|
|
|
|
|
|
if (res := check_ipv6_avail()) < 0:
|
|
|
|
pytest.skip(f"IPv6 not avail, retcode: {res}")
|
|
|
|
|
2021-12-06 19:23:35 +01:00
|
|
|
sql_chk = f"""
|
|
|
|
set list on;
|
|
|
|
commit;
|
2024-06-13 09:13:02 +02:00
|
|
|
connect 'inet4://127.0.0.1/{act.db.db_path}';
|
2021-12-06 19:23:35 +01:00
|
|
|
|
|
|
|
select mon$remote_protocol as procotol_when_connect_from_isql
|
|
|
|
from mon$attachments where mon$attachment_id = current_connection;
|
|
|
|
|
|
|
|
set term ^;
|
|
|
|
execute block returns(protocol_when_connect_by_es_eds varchar(20) ) as
|
|
|
|
declare stt varchar(255) = 'select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection';
|
|
|
|
begin
|
|
|
|
for
|
|
|
|
execute statement (stt)
|
2024-06-13 09:13:02 +02:00
|
|
|
on external 'inet4://127.0.0.1/{act.db.db_path}'
|
2022-01-25 22:55:48 +01:00
|
|
|
as user '{act.db.user}' password '{act.db.password}'
|
2021-12-06 19:23:35 +01:00
|
|
|
into protocol_when_connect_by_es_eds
|
|
|
|
do
|
|
|
|
suspend;
|
|
|
|
end
|
|
|
|
^
|
|
|
|
set term ;^
|
|
|
|
commit;
|
|
|
|
|
2024-06-14 10:09:48 +02:00
|
|
|
-- since 27.10.2019; checked again 13.06.2024
|
|
|
|
connect 'inet6://[::1]/{act.db.db_path}';
|
2021-12-06 19:23:35 +01:00
|
|
|
|
|
|
|
select mon$remote_protocol as procotol_when_connect_from_isql
|
|
|
|
from mon$attachments where mon$attachment_id = current_connection;
|
|
|
|
|
|
|
|
set term ^;
|
|
|
|
execute block returns(protocol_when_connect_by_es_eds varchar(20) ) as
|
|
|
|
declare stt varchar(255) = 'select mon$remote_protocol from mon$attachments where mon$attachment_id = current_connection';
|
|
|
|
begin
|
|
|
|
for
|
|
|
|
execute statement (stt)
|
2024-06-14 10:09:48 +02:00
|
|
|
-- Failed before fix #8156 ("Can not specify concrete IPv6 address in ES/EDS connection string"):
|
|
|
|
on external 'inet6://[::1]/{act.db.db_path}'
|
2022-01-25 22:55:48 +01:00
|
|
|
as user '{act.db.user}' password '{act.db.password}'
|
2021-12-06 19:23:35 +01:00
|
|
|
into protocol_when_connect_by_es_eds
|
|
|
|
do
|
|
|
|
suspend;
|
|
|
|
end
|
|
|
|
^
|
|
|
|
set term ;^
|
|
|
|
commit;
|
2024-06-13 09:13:02 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
expected_stdout = """
|
|
|
|
PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv4
|
|
|
|
PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv4
|
|
|
|
PROCOTOL_WHEN_CONNECT_FROM_ISQL TCPv6
|
|
|
|
PROTOCOL_WHEN_CONNECT_BY_ES_EDS TCPv6
|
|
|
|
"""
|
2021-04-26 20:07:00 +02:00
|
|
|
|
2022-01-25 22:55:48 +01:00
|
|
|
act.expected_stdout = expected_stdout
|
2024-06-13 09:13:02 +02:00
|
|
|
act.isql(switches=['-q', f'inet://{act.db.db_path}'], input=sql_chk, connect_db=False)
|
2022-01-25 22:55:48 +01:00
|
|
|
assert act.clean_stdout == act.clean_expected_stdout
|
2021-04-26 20:07:00 +02:00
|
|
|
|