The branch, master has been updated via 3f4660900a7 selftest: test tsocket_address_inet_from_hostport_strings via 262148721ee selftest: add more tests for test_address_inet_from_strings via c26fcef50d0 WHATSNEW: document dns forwarder change via 2a098030977 libcli/dns.c: dns forwarder port test changes via 617a5a1d357 libcli/dns: smb.conf dns forwarder port support via f39a06de3be lib/tsocket: new function to parse host port strs. via 775939823a5 libcli/dns: dns forwarder port doc changes via 860d8902a9c pyldb: Make ldb.Message containment testing consistent with indexing via 865fe238599 pyldb: Add tests for ldb.Message containment testing via 22353767ca7 pyldb: Raise TypeError for an invalid ldb.Message index via b018e51d272 pyldb: Add test for an invalid ldb.Message index type via fb758c32e76 s4/torture/drs/python: Fix attribute existence check via 9d25a21d602 pyldb: Fix deleting an ldb.Control critical flag via b1adaa517c1 pytest:segfault: Add test for deleting an ldb.Control critical flag via d7af772de88 pyldb: Fix deleting an ldb.Message dn via 6a041f6a99c pytest:segfault: Add test for deleting an ldb.Message dn from 81e27693c62 mdssvc: Use ndr_policy_handle_empty()
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 3f4660900a71816df505c2e634eef86a86afcda3 Author: Uri Simchoni <u...@samba.org> Date: Thu Sep 16 20:03:59 2021 +0300 selftest: test tsocket_address_inet_from_hostport_strings Signed-off-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Sep 28 10:34:12 UTC 2021 on sn-devel-184 commit 262148721ee6d794f7f2d1ad1b36e00a1401ec41 Author: Uri Simchoni <u...@samba.org> Date: Thu Sep 16 20:03:02 2021 +0300 selftest: add more tests for test_address_inet_from_strings Test the case of NULL address as input Signed-off-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c26fcef50d09d3d70c646f3151dda265d4b0eb92 Author: Uri Simchoni <u...@samba.org> Date: Thu Sep 16 10:11:46 2021 +0300 WHATSNEW: document dns forwarder change Signed-off-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 2a098030977d7720436b7850fa731557eeb70bc2 Author: Matthew Grant <m...@mattgrant.net.nz> Date: Sat Sep 18 10:05:24 2021 +1200 libcli/dns.c: dns forwarder port test changes Test harness for the dns fowarder setting in smb.conf. Adds IPv6 forwarder as second target DNS forwarder, listening on port 54. Signed-off-by: Matthew Grant <gran...@mattgrant.net.nz> Reviewed-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 617a5a1d3579b27de0e2b0736909ca83b7b3ee15 Author: Matthew Grant <m...@mattgrant.net.nz> Date: Sat Sep 18 10:02:11 2021 +1200 libcli/dns: smb.conf dns forwarder port support Call new tsocket_address_inet_from_hostport_strings() instead of tsocket_address_inet_from_strings() to implement setting a port to query for a DNS forwarder. Signed-off-by: Matthew Grant <gran...@mattgrant.net.nz> Reviewed-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f39a06de3bea9ec03a3e82c8892d9e572abd1163 Author: Matthew Grant <m...@mattgrant.net.nz> Date: Sun Sep 19 17:41:42 2021 +1200 lib/tsocket: new function to parse host port strs. tsocket_address_inet_from_hostport_strings() on top of tsocket_address_inet_from_strings(), implementing the ability to parse a port number appended to an IPv6 or IPv4 address. IPv6 addresses can also optionally have square brackets around them, but these are needed to specify the port number as colon is used to delimit port from the IP address in the string. Note that this code just recognises and parses the strings with port given, or just IPv6 with square brackets. The rest of the parsing is passed on to tsocket_address_inet_from strings(), and errors from there passed back up the stack. Signed-off-by: Matthew Grant <gran...@mattgrant.net.nz> Reviewed-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 775939823a5a956acc236c808d5aee78cbd9e132 Author: Matthew Grant <m...@mattgrant.net.nz> Date: Sat Sep 18 09:57:26 2021 +1200 libcli/dns: dns forwarder port doc changes Documentation changes specifying how list entries for dns forwarder are to be specified with ability to add trailing target port number. Signed-off-by: Matthew Grant <gran...@mattgrant.net.nz> Reviewed-by: Uri Simchoni <u...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 860d8902a9c502d4be83396598cf4a53c80fea69 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 14:39:59 2021 +1200 pyldb: Make ldb.Message containment testing consistent with indexing Previously, containment testing using the 'in' operator was handled by performing an equality comparison between the chosen object and each of the message's keys in turn. This behaviour was prone to errors due to not considering differences in case between otherwise equal elements, as the indexing operations do. Containment testing should now be more consistent with the indexing operations and with the get() method of ldb.Message. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 865fe238599a732360b77e06e592cb85d459acf8 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 13:48:57 2021 +1200 pyldb: Add tests for ldb.Message containment testing These tests verify that the 'in' operator on ldb.Message is consistent with indexing and the get() method. This means that the 'dn' element should always be present, lookups should be case-insensitive, and use of an invalid type should result in a TypeError. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 22353767ca75af9d9e8fa1e7da372dcb5eddfcb7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 13:39:56 2021 +1200 pyldb: Raise TypeError for an invalid ldb.Message index Previously, a TypeError was raised and subsequently overridden by a KeyError. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b018e51d2725a23b2fedd3058644b8021f6a6a06 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 13:22:05 2021 +1200 pyldb: Add test for an invalid ldb.Message index type BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fb758c32e7633178f42dc2c031667b10c2ca6e90 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 19:18:39 2021 +1200 s4/torture/drs/python: Fix attribute existence check BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9d25a21d6024c6c2f8e4634f45e3944d8acbf8b8 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 11:16:09 2021 +1200 pyldb: Fix deleting an ldb.Control critical flag BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b1adaa517c1237a473bdcf818523f5107df3d6b0 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 11:13:02 2021 +1200 pytest:segfault: Add test for deleting an ldb.Control critical flag BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d7af772de88885f46708329ff7bb5798da91d2c7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 11:12:16 2021 +1200 pyldb: Fix deleting an ldb.Message dn BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6a041f6a99c39632d5c32e9d53b06719c20bef2c Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Sat Sep 25 10:56:25 2021 +1200 pytest:segfault: Add test for deleting an ldb.Message dn BUG: https://bugzilla.samba.org/show_bug.cgi?id=14845 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 9 + docs-xml/smbdotconf/domain/dnsforwarder.xml | 8 +- lib/ldb/pyldb.c | 49 ++++-- lib/ldb/tests/python/api.py | 29 ++++ lib/tsocket/tests/test_bsd_addr.c | 186 +++++++++++++++++++++ lib/tsocket/tsocket.h | 43 +++++ lib/tsocket/tsocket_bsd.c | 100 +++++++++++ libcli/dns/dns.c | 8 +- python/samba/tests/dns_forwarder.py | 17 +- python/samba/tests/dns_forwarder_helpers/server.py | 10 +- python/samba/tests/segfault.py | 14 ++ selftest/target/Samba4.pm | 4 +- source4/torture/drs/python/replica_sync.py | 2 +- 13 files changed, 449 insertions(+), 30 deletions(-) Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index b585e2e20a1..73cbe8d0392 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -29,6 +29,14 @@ certmonger paired with cepces to monitor the host certificate templates. Certificates are installed in /var/lib/samba/certs and private keys are installed in /var/lib/samba/private/certs. +Ability to add ports to dns forwarder addresses in internal DNS backend +----------------------------------------------------------------------- + +The internal DNS server of Samba forwards queries non-AD zones to one or more +configured forwarders. Up until now it has been assumed that these forwarders +listen on port 53. Starting with this version it is possible to configure the +port using host:port notation. See smb.conf for more details. Existing setups +are not affected, as the default port is 53. REMOVED FEATURES ================ @@ -50,6 +58,7 @@ smb.conf changes Parameter Name Description Default -------------- ----------- ------- kernel share modes New default No + dns forwarder Changed KNOWN ISSUES diff --git a/docs-xml/smbdotconf/domain/dnsforwarder.xml b/docs-xml/smbdotconf/domain/dnsforwarder.xml index f65740a7a24..cf8875ea5a0 100644 --- a/docs-xml/smbdotconf/domain/dnsforwarder.xml +++ b/docs-xml/smbdotconf/domain/dnsforwarder.xml @@ -8,10 +8,14 @@ </para> <para>The DNS forwarder is only used if the internal DNS server - in Samba is used. + in Samba is used. Port numbers can be appended by separating them from + the address by using a colon (':'). When specifying a port, IPv6 + addresses must be enclosed in square brackets ('[' and ']'). IPv6 + forwarder addresses with no port specified, don't need the square + brackets, and default to port 53. </para> </description> <value type="default"></value> -<value type="example">192.168.0.1 192.168.0.2</value> +<value type="example">192.168.0.1 192.168.0.2 ::1 [2001:db8::1] [2001:db8:1:2::1]:54 </value> </samba:parameter> diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index f1538b37c6b..3f4b0c7a45c 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -182,6 +182,10 @@ static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self, static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure) { + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete critical flag"); + return -1; + } if (PyObject_IsTrue(value)) { self->data->critical = true; } else { @@ -3429,33 +3433,41 @@ static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self, return obj; } -static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name) +static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name) { - struct ldb_message_element *el; - const char *name; + struct ldb_message_element *el = NULL; + const char *name = NULL; struct ldb_message *msg = pyldb_Message_AsMessage(self); name = PyUnicode_AsUTF8(py_name); if (name == NULL) { - PyErr_SetNone(PyExc_TypeError); - return NULL; + return -1; } - if (!ldb_attr_cmp(name, "dn")) - return pyldb_Dn_FromDn(msg->dn); - el = ldb_msg_find_element(msg, name); - if (el == NULL) { - return NULL; + if (!ldb_attr_cmp(name, "dn")) { + return 1; } - return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); + el = ldb_msg_find_element(msg, name); + return el != NULL ? 1 : 0; } static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name) { - PyObject *ret = py_ldb_msg_getitem_helper(self, py_name); - if (ret == NULL) { + struct ldb_message_element *el = NULL; + const char *name = NULL; + struct ldb_message *msg = pyldb_Message_AsMessage(self); + name = PyUnicode_AsUTF8(py_name); + if (name == NULL) { + return NULL; + } + if (!ldb_attr_cmp(name, "dn")) { + return pyldb_Dn_FromDn(msg->dn); + } + el = ldb_msg_find_element(msg, name); + if (el == NULL) { PyErr_SetString(PyExc_KeyError, "No such element"); return NULL; } - return ret; + + return PyLdbMessageElement_FromMessageElement(el, msg->elements); } static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs) @@ -3665,6 +3677,10 @@ static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self) return pyldb_Message_AsMessage(self)->num_elements; } +static PySequenceMethods py_ldb_msg_sequence = { + .sq_contains = (objobjproc)py_ldb_msg_contains, +}; + static PyMappingMethods py_ldb_msg_mapping = { .mp_length = (lenfunc)py_ldb_msg_length, .mp_subscript = (binaryfunc)py_ldb_msg_getitem, @@ -3741,6 +3757,10 @@ static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure) static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure) { struct ldb_message *msg = pyldb_Message_AsMessage(self); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, "cannot delete dn"); + return -1; + } if (!pyldb_Dn_Check(value)) { PyErr_SetString(PyExc_TypeError, "expected dn"); return -1; @@ -3838,6 +3858,7 @@ static PyTypeObject PyLdbMessage = { .tp_name = "ldb.Message", .tp_methods = py_ldb_msg_methods, .tp_getset = py_ldb_msg_getset, + .tp_as_sequence = &py_ldb_msg_sequence, .tp_as_mapping = &py_ldb_msg_mapping, .tp_basicsize = sizeof(PyLdbMessageObject), .tp_dealloc = (destructor)py_ldb_msg_dealloc, diff --git a/lib/ldb/tests/python/api.py b/lib/ldb/tests/python/api.py index 16b71e2e650..bf6f7ef993d 100755 --- a/lib/ldb/tests/python/api.py +++ b/lib/ldb/tests/python/api.py @@ -3082,6 +3082,12 @@ class LdbMsgTests(TestCase): def test_notpresent(self): self.assertRaises(KeyError, lambda: self.msg["foo"]) + def test_invalid(self): + try: + self.assertRaises(TypeError, lambda: self.msg[42]) + except KeyError: + self.fail() + def test_del(self): del self.msg["foo"] @@ -3197,6 +3203,29 @@ class LdbMsgTests(TestCase): def test_get_unknown_text(self): self.assertEqual(None, self.msg.text.get("lalalala")) + def test_contains(self): + self.msg['foo'] = ['bar'] + self.assertIn('foo', self.msg) + + self.msg['Foo'] = ['bar'] + self.assertIn('Foo', self.msg) + + def test_contains_case(self): + self.msg['foo'] = ['bar'] + self.assertIn('Foo', self.msg) + + self.msg['Foo'] = ['bar'] + self.assertIn('foo', self.msg) + + def test_contains_dn(self): + self.assertIn('dn', self.msg) + + def test_contains_dn_case(self): + self.assertIn('DN', self.msg) + + def test_contains_invalid(self): + self.assertRaises(TypeError, lambda: None in self.msg) + def test_msg_diff(self): l = ldb.Ldb() msgs = l.parse_ldif("dn: foo=bar\nfoo: bar\nbaz: do\n\ndn: foo=bar\nfoo: bar\nbaz: dont\n") diff --git a/lib/tsocket/tests/test_bsd_addr.c b/lib/tsocket/tests/test_bsd_addr.c index 9f9fa29ec2d..ac6e798b952 100644 --- a/lib/tsocket/tests/test_bsd_addr.c +++ b/lib/tsocket/tests/test_bsd_addr.c @@ -163,6 +163,191 @@ static void test_address_inet_from_strings(void **state) assert_int_equal(rc, -1); assert_int_not_equal(save_errno, 0); assert_null(addr); + + /* + * Unspecified IP family, given NULL, verify it returns something + */ + rc = tsocket_address_inet_from_strings(mem_ctx, "ip", NULL, 1234, + &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + TALLOC_FREE(addr); + + /* + * IPv4, given NULL, verify it returns 0.0.0.0 + */ + rc = tsocket_address_inet_from_strings(mem_ctx, "ipv4", NULL, 1234, + &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv4:0.0.0.0:1234"); + assert_true(tsocket_address_is_inet(addr, "ip")); + assert_true(tsocket_address_is_inet(addr, "ipv4")); + assert_false(tsocket_address_is_inet(addr, "ipv6")); + assert_int_equal(tsocket_address_inet_port(addr), 1234); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * IPv6, given NULL, verify it returns :: + */ + rc = tsocket_address_inet_from_strings(mem_ctx, "ipv6", NULL, 1234, + &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv6::::1234"); + assert_true(tsocket_address_is_inet(addr, "ip")); + assert_false(tsocket_address_is_inet(addr, "ipv4")); + assert_true(tsocket_address_is_inet(addr, "ipv6")); + assert_int_equal(tsocket_address_inet_port(addr), 1234); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); +} + +static void test_address_inet_from_hostport_strings(void **state) +{ + int rc = 0; + int save_errno; + TALLOC_CTX *mem_ctx = *state; + struct tsocket_address *addr = NULL; + char *addr_s = NULL; + + /* + * IPv4 host:port + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "1.2.3.4:5678", 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv4:1.2.3.4:5678"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * IPv4 host + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "1.2.3.4", 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv4:1.2.3.4:1234"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * IPv6 [host]:port + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "[2001::1]:5678", 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv6:2001::1:5678"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * IPv6 [host] + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "[2001::1]", 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv6:2001::1:1234"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * IPv6 host + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "2001::1", 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv6:2001::1:1234"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * Given NULL, verify it returns something + */ + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ipv6", NULL, 1234, &addr); + assert_return_code(rc, errno); + assert_non_null(addr); + addr_s = tsocket_address_string(addr, mem_ctx); + assert_non_null(addr_s); + assert_string_equal(addr_s, "ipv6::::1234"); + TALLOC_FREE(addr); + TALLOC_FREE(addr_s); + + /* + * [host]grarbage + */ + errno = 0; + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "[2001::1]garbage", 1234, &addr); + save_errno = errno; + assert_int_equal(rc, -1); + assert_int_not_equal(save_errno, 0); + assert_null(addr); + + /* + * [host]:grarbage + */ + errno = 0; + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "[2001::1]:garbage", 1234, &addr); + save_errno = errno; + assert_int_equal(rc, -1); + assert_int_not_equal(save_errno, 0); + assert_null(addr); + + /* + * host:grarbage + */ + errno = 0; + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "1.2.3.4:garbage", 1234, &addr); + save_errno = errno; + assert_int_equal(rc, -1); + assert_int_not_equal(save_errno, 0); + assert_null(addr); + + /* + * [host]:<port-too-large> + */ + errno = 0; + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "[2001::1]:100000", 1234, &addr); + save_errno = errno; + assert_int_equal(rc, -1); + assert_int_not_equal(save_errno, 0); + assert_null(addr); + + /* + * host:<port-too-large> + */ + errno = 0; + rc = tsocket_address_inet_from_hostport_strings( + mem_ctx, "ip", "1.2.3.4:100000", 1234, &addr); + save_errno = errno; + assert_int_equal(rc, -1); + assert_int_not_equal(save_errno, 0); + assert_null(addr); } int main(int argc, char *argv[]) @@ -170,6 +355,7 @@ int main(int argc, char *argv[]) int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(test_address_inet_from_strings), + cmocka_unit_test(test_address_inet_from_hostport_strings), }; if (argc == 2) { diff --git a/lib/tsocket/tsocket.h b/lib/tsocket/tsocket.h index 2f1c7981346..d3cde99bf5a 100644 --- a/lib/tsocket/tsocket.h +++ b/lib/tsocket/tsocket.h @@ -539,6 +539,49 @@ int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx, __location__) #endif +#ifdef DOXYGEN +/** + * @brief Create a tsocket_address for ipv4 and ipv6 endpoint addresses. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fam The family can be can be "ipv4", "ipv6" or "ip". With + * "ip" it autodetects "ipv4" or "ipv6" based on the + * addr. + * + * @param[in] host_port_addr A valid ip address string based on the + * selected family (dns names are not allowed!). A port + * number may follow sepatated by a colon. IPv6 may be + * surrounded in square brackets, and these are required + * if appending a port number. It's valid to pass NULL, + * which gets mapped to "0.0.0.0" or "::". + * + * @param[in] default_port A valid port number for the default port if none + * given. + * + * @param[out] _addr A tsocket_address pointer to store the information. + * + * @return 0 on success, -1 on error with errno set. + */ +int tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr); +#else +int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr, + const char *location); + +#define tsocket_address_inet_from_hostport_strings( \ + mem_ctx, fam, host_port_addr, default_port, _addr) \ + _tsocket_address_inet_from_hostport_strings( \ + mem_ctx, fam, host_port_addr, default_port, _addr, __location__) +#endif + /** * @brief Get the address of an 'inet' tsocket_address as a string. * diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c index 9485da7c8af..5650763d1e6 100644 --- a/lib/tsocket/tsocket_bsd.c +++ b/lib/tsocket/tsocket_bsd.c @@ -29,6 +29,7 @@ #include "lib/util/iov_buf.h" #include "lib/util/blocking.h" #include "lib/util/util_net.h" +#include "lib/util/samba_util.h" static int tsocket_bsd_error_from_errno(int ret, int sys_errno, @@ -441,6 +442,105 @@ done: return ret; } +int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx, + const char *fam, + const char *host_port_addr, + uint16_t default_port, + struct tsocket_address **_addr, + const char *location) +{ + char *pl_sq = NULL; + char *pr_sq = NULL; + char *pl_period = NULL; + char *port_sep = NULL; + char *cport = NULL; + char *buf = NULL; + uint64_t port = 0; + int ret; + char *s_addr = NULL; + uint16_t s_port = default_port; + bool conv_ret; + bool is_ipv6_by_squares = false; + + if (host_port_addr == NULL) { + /* got straight to next function if host_port_addr is NULL */ + goto get_addr; + } + buf = talloc_strdup(mem_ctx, host_port_addr); + if (buf == NULL) { + errno = ENOMEM; + return -1; + } + pl_period = strchr_m(buf, '.'); -- Samba Shared Repository