calimero-project / calimero-core

Core library for KNX network access and management
Other
128 stars 65 forks source link

LocalEP in case of tunneling: Sense? #43

Closed tuxedo0801 closed 6 years ago

tuxedo0801 commented 7 years ago

Hi there,

struggling (again) with the tunneling mode. It works for windows, but not for linux. I get an IOException telling me that the given argument is invalid. This happens on first UDP datagra sending...

I've broken down the issue to this line:

https://github.com/calimero-project/calimero-core/blob/master/src/tuwien/auto/calimero/link/KNXNetworkLinkIP.java#L190

The local endpoint is used to tell the udp datagram socket where the data to be sent comes from. On windows it seems that InetAddress.getLocalHost() gives the correct and useable network IP address of the host (not localhost ip), but on linux all of my systems resolve to "myhostname:127.0.1.1:0". And this localhost IP cannot be used as an endpoint (of course...).

It makes no sense for me to change my local name resolution, as other services rely more or less on this kind of localhost IP.

So question is: What sense does it make to tell the operating system which endpoint to use. Why not provide no endpoint at all and let the OS decide?!

tuxedo0801 commented 7 years ago

I just saw that the local endpoint is also used in HPAI. Sadly, I have no exact idea what this is about und if this is required.

Just for UDP communication, the endpoint is not required. So it would be good if it works without one.

Otherwise one has to either

I asked the linux community why by default, the local hostname resolves to 127.0.1.1. Answer (in german):

"damit lokale Dienste schneller (resourcen-schonender) erreichbar sind damit lokale Dienste auch erreichbar sind, wenn das Netzwerk nicht erreichbar ist"

For me all in all valid answers.

So how to continue?

tuxedo0801 commented 7 years ago

I tried and experimented a bit... I'm now able to establish a TUNNELING connection with a custom localEP. This would work, BUT:

It would really make sense to let Java resp. the underlying OS decide which endpoint to use. And for HPA/HeartbeatI: Maybe check which endpoint java/the OS finally uses? Or also just let the OS decide....

Please comment ....

tuxedo0801 commented 7 years ago

I testwise removed the use of forced local-ep (which would result to 127.0.1.1) and forced the Heartbeat to use "nat-mode" (=no local endpoint).

Works fine so far.

calimero-project commented 7 years ago

but on linux all of my systems resolve to "myhostname:127.0.1.1:0". And this localhost IP cannot be used as an endpoint (of course...).

it can be used as endpoint.This IP is as valid as any other IP's endpoint. It just limits your connection to your own host. Can be useful, might not be. The invalid argument is caused by your server IP which is not "valid" for that interface.

Why not provide no endpoint at all and let the OS decide

well, the problem you describe in #37 is one of the reasons why not. One would use a wildcard IP, and has the problem that the HPAI requires a known, valid, and reachable IP address for the duration of the connection. An empty field in the HPAI indicates NATting. Not all servers support NAT. It works for your server, but won't for others.

Even if I change /etc/hosts [...] /etc/hosts is simply a shortcut. This is also explained in the answers you quoted for linux.

In general, if you use dhcp, also the server ip can change.

Relying on getLocalHost is somewhat legacy from when there was a constructor that depended on that (that was like >10 years ago, and most had a Windows/ETS setup, almost always with a single interface).

I have occasionally used the library with subnet matching for IPv4/non-NAT connections instead. Actually I think that would be the most useful solution to what you describe. I can put it on a branch, if you want to try it out.

tuxedo0801 commented 7 years ago

it can be used as endpoint.This IP is as valid as any other IP's endpoint. It just limits your connection to your own host. Can be useful, might not be.

I can't think of a useful usecase for calimero talking to localhost only ... So at least for me: not useful at all.

One would use a wildcard IP, and has the problem that the HPAI requires a known, valid, and reachable IP address for the duration of the connection. An empty field in the HPAI indicates NATting. Not all servers support NAT.

Is the described HPAI behavior specified by KNX IP Specification or so? Or is this just the current implementation?

The problem I currently have: There is no NAT. So why would HPAI indicate NAT, when there is no NAT?

Do you have more information about HPAI so that I further digg into it?

In general, if you use dhcp, also the server ip can change.

It can, but, no, it will not: As from my experience, a serios network administrator will give the static servers a static, well defined IP, whereas client systems mostly rely on DHCP. The problem is: Calimero can be used as/on server system, as well as on client system. In my case, it's a client system.

I have occasionally used the library with subnet matching for IPv4/non-NAT connections instead. Actually I think that would be the most useful solution to what you describe. I can put it on a branch, if you want to try it out.

That sounds interesting. I will have a look at it if you put it online...

tuxedo0801 commented 7 years ago

Any update on this?

calimero-project commented 7 years ago

I created the branch feat/same-ip-subnet with the change to try as mentioned before: KNXNetworkLinkIP will use the same ip subnet for ipv4/non-nat connection, if you pass null as local endpoint.

calimero-project commented 6 years ago

IPv4 subnet matching was introduced with 89b6af0c96cdb07bf72339e3b7f6c895d35523c5. So using a wildcard address (new InetSocketAddress(0)) as local endpoint will match it to the subnet of the remote endpoint, no localhost lookup necessary. (For obvious reasons this doesn't apply in NATted networks.)