Indy 10 and setting socket options - delphi

Maybe the solution to this is very simple and I'm just too dumb to see it.
I need to recompile an old application with Indy 10 and there's this line that used to be
inUDPServer.Binding.SetSockOpt(Id_IPPROTO_IP, Id_IP_ADD_MEMBERSHIP, PChar(#mreq), SizeOf(mreq));
but the new TIdSocketHandle.SetSockOpt takes 3 integers.
Now how am I supposed to provide the ip_mreq? Just passing the imr_multiaddr.S_addr results in an #10014 Error - Buffer fault.
Maybe one of you guys has an idea.
Cheers Andy

Use the TIdSocketHandle.AddMulticastMembership() method instead (if your version of Indy 10 does not have that method available, then you will have to update to a newer snapshot first), eg:
inUDPServer.Binding.AddMulticastMembership('Group IP address');
It adds the TIdSocketHandle.IP address to the membership of the specified Group IP. IPs can be specified as either IPv4 or IPv6, depending on the setting of the TIdSocketHandle.IPVersion property.
Alternatively, consider using the TIdIPMCastServer and TIdIPMCastClient components instead of TIdUDPServer directly.

Related

Is the ADO Recordset.CacheSize property meaningful for a client-side cursor?

If I have an ADO Connection with CursorLocationType.adUseClient and I use it to open a Recordset, then does setting the Recordset.CacheSize property have any effect?
From CacheSize Property
Use the CacheSize property to control how many records to retrieve at one time into local memory from the provider.
And from The Significance of Cursor Location:
In ADO, call for a client-side cursor by using the adUseClient CursorLocationEnum. With a non-keyset client-side cursor, the server sends the entire result set across the network to the client computer.
It seems to me that setting CacheSize will have no effect for a client-side cursor, because the records are already in local memory. But I can't find any official documentation that explicitly says this. I can only find blog posts like this one that says:
We will be using ClientSide cursors ... The CacheSize tells ADO to cache N number of rows on the cursor. Since we chose to have 10 records per page, I set the cache size to 10. ADO will grab the first 10 records, and cache those. It won't hit the database until you request any past the cached limit.
but this seems to contradict "the server sends the entire result set across the network to the client computer."
So what actually happens?

Permission needed for using GetTableNames

I have a Delphi/C++ builder app that uses Firedac to connect to a Sybase ASE database using the ODBC connection. When connection to the database, if I use the database's system admin (SA) user id/password, everything works fine and GetTableNames comes back with the list of tables in the database. But if I use a regular user to connect to database, GetTableNames comes back with an empty list. My question is, what permissions should I give the regular user for this to work.And as a side question, does anyone know what kind of command Firedac sends to database to get the table names?My code in Delphi looks like:
DBConnection.GetTableNames('', '', '', tableNameList, [TFDPhysObjectScope.osMy], [TFDPhysTableKind.tkTable]);
and in C++ Builder it looks like:
DBConnection->GetTableNames(L"", L"", L"", tableNameList, TFDPhysObjectScopes() << TFDPhysObjectScope::osMy, TFDPhysTableKinds() << TFDPhysTableKind::tkTable);
Thank youSam
For generic ODBC drivers it's the SQLTables function that FireDAC calls. Unfortunately, for the SAP Adaptive Server Enterprise driver I haven't found any information about the implementation of this function. It is the implementation detail, so it's not the issue.
The only note I found is this (for different products), for example:
sp_tables
This function corresponds to the ODBC function SQLTables.
So it's possible that the ODBC driver calls the sp_tables stored procedure in its SQLTables function implementation for that product, but no one explicitly said that (only that it corresponds).
What's more, for SAP Adaptive Server Enterprise, there is no such note by its sp_tables procedure. But you can give it a try. Or better yet, if you have some kind of command monitoring tool, use it to track what your driver calls from its SQLTables function implementation.
In any case, it is an implementation detail you should not care about, nor rely on.
The problem was NOT permissions, it was the 5th parameter of GetTableNames. The 5th parameter is the Scope which determines what kind of tables would be reported back. osMy means tables/objects owned by the logged-in user. But normally all tables in a database, are owned by SA/dbo. Adding osOther to the parameter will fix the problem. So the correct way of calling the function in Delphi would be:
DBConnection.GetTableNames('', '', '', tableNameList, [TFDPhysObjectScope.osMy, TFDPhysObjectScope.osOther], [TFDPhysTableKind.tkTable]);
and in C++ Builder it should look like:
DBConnection->GetTableNames(L"", L"", L"", tableNameList, TFDPhysObjectScopes() << TFDPhysObjectScope::osMy << TFDPhysObjectScope::osOther, TFDPhysTableKinds() << TFDPhysTableKind::tkTable);
Which will return the name of all tables that are not system tables.I must mention that I blame Embarcadero for poor documentation of TFDPhysObjectScope. The documentation does NOT explain what any of these values means. Way too often (as in this case) we see this:
Embarcadero Technologies does not currently have any additional
information. Please help us document this topic by using the
Discussion page!
And we are forced to guess and/or try-fail.

How can I retrieve deleted objects from Active Directory with Ruby?

From the research I've done, it appears I need to send a special OID with my request (1.2.840.113556.1.4.417) in order to access the Deleted Objects container.
I couldn't find a way to send a specific control with a request using the "net-ldap" gem. Does anyone know if this is possible?
There is another gem, ruby-ldap, which appears to be more flexible and it seems I can send controls with my request (e.g. using the search_ext2() method).
However, no matter what I try, I am not getting back any objects, even though I know they haven't been garbage collected yet.
I'm including the filter "isDeleted=TRUE" with my requests as well.
OK, I finally figured it out. One will need to use the ruby-ldap gem. The reason my controls were not being sent was because the LDAP Protocol Version (LDAP::LDAP_OPT_PROTOCOL_VERSION) had defaulted to v2 and apparently it must be v3.
The following is a snippet that works:
require 'ldap'
conn = LDAP::Conn.new('yourserver.example.com', 389)
conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
conn.bind("CN=Administrator,CN=Users,DC=example,DC=com", "sekritpass")
# controlType: 1.2.840.113556.1.4.417 (LDAP_SERVER_SHOW_DELETED_OID)
control = LDAP::Control.new('1.2.840.113556.1.4.417')
conn.search_ext2('CN=Deleted Objects,DC=example,DC=com', LDAP::LDAP_SCOPE_SUBTREE, "(isDeleted=*)", nil, false, [control], nil)
The filter (isDeleted=*) isn't necessarily required, you could also simply use (objectClass=*). You can also use the scope LDAP::LDAP_SCOPE_ONELEVEL if desired.
Have you tried isDeleted=* instead?
https://technet.microsoft.com/en-us/library/cc978013.aspx

How to filter wireshark to display only packets between a server and a client?

I am new to wireshark and trying to write simple filters. What i am trying to do is the following: I want to write a filter so that only the packets between my computer and a specified server appear in the packets pane. Here is what i tried:
ip.src==159.20.94.8 and ip.dst==10.1.1.7
First one is the ip address of my computer, and second one is the ip address of the server. But there is also the opposite of this, in which source is the server and destination is my computer.
ip.src==10.1.1.7 and ip.dst==159.20.94.8
So my question is, how can i combine these two filters? Or is there a simpler way for this filtering?
Thanks
Use ip.addr==159.20.94.8 and ip.addr==10.1.1.7
I know that doesn't seem to make sense, but ip.addr matches either source or destination.
Use ip.addr==10.0.0.1 or ip.addr==10.0.0.2.
Using the OR operator will give you results in both ways(Source and Destination).

Get all IPs in the same network as my computer

Is there any way to programatically (in c#) get all the other workstations that are in the same domain/subnetwork as my computer and display some information about them (if they are active, what kind of OS they have installed, their IP etc)?
nmap does this plus a ton more. Its open source.
This is a VB solution, but I'm pretty sure you'll be able to make the changes you need to make this work!
There's probably a better way, but this was a first cut.
Imports System.Net.NetworkInformation
Imports System.Directory Services
Class NetworkInfo
Function GetComputers() as list(Of String)
dim List as new list(of String)
Dim DomainEntry as new DirectoryEntry("WinNT://" + DomainInfo.GetDomain.Trim())
DomainEntry.Children.SchemaFilter.Add("computer")
For Each Machine as DirectoryEntry in DomainEntry.Children
List.Add(Machine.Name)
Next
return List
End Function
End Class
There are all sorts of useful tools knocking about in the System.Net.NetworkInformation namespace to let you capture things like the IP address, etc.
The simplest approach that I can think of (which is far from fool proof) is to send an ICMP echo request (defined in RFC 792) to 224.0.0.1. C# provides the Ping class to do this. Keep in mind though that you run the risk of dropped packets, there is also the question as to whether or not all the machines on the network support multicast.

Resources