6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 21:43:06 +01:00
firebird-qa/tests/bugs/core_5229_test.py

159 lines
6.1 KiB
Python

#coding:utf-8
"""
ID: issue-5508
ISSUE: https://github.com/FirebirdSQL/firebird/issues/5508
TITLE: Allow to enforce IPv4 or IPv6 in URL-like connection strings
DESCRIPTION:
JIRA: CORE-5229
FBTEST: bugs.core_5229
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.
2. Attempt to specify explicitly IPv6 address "[::1]" in ES/EDS caused error:
========
Statement failed, SQLSTATE = 42000
External Data Source provider 'inet6://[' not found
========
It was fixed in gh-8156.
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.
[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
"""
import pytest
from firebird.qa import *
db = db_factory()
act = python_act('db')
#------------------------------------------
# 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
#------------------------------------------
@pytest.mark.es_eds
@pytest.mark.version('>=3.0.1')
def test_1(act: Action):
if (res := check_ipv6_avail()) < 0:
pytest.skip(f"IPv6 not avail, retcode: {res}")
sql_chk = f"""
set list on;
commit;
connect 'inet4://127.0.0.1/{act.db.db_path}';
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)
on external 'inet4://127.0.0.1/{act.db.db_path}'
as user '{act.db.user}' password '{act.db.password}'
into protocol_when_connect_by_es_eds
do
suspend;
end
^
set term ;^
commit;
-- since 27.10.2019; checked again 13.06.2024
connect 'inet6://[::1]/{act.db.db_path}';
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)
-- Failed before fix #8156 ("Can not specify concrete IPv6 address in ES/EDS connection string"):
on external 'inet6://[::1]/{act.db.db_path}'
as user '{act.db.user}' password '{act.db.password}'
into protocol_when_connect_by_es_eds
do
suspend;
end
^
set term ;^
commit;
"""
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
"""
act.expected_stdout = expected_stdout
act.isql(switches=['-q', f'inet://{act.db.db_path}'], input=sql_chk, connect_db=False)
assert act.clean_stdout == act.clean_expected_stdout