13/01/2007
Log4Net: IP parsing bug when used with framework .NET 2.0
Posted by Olivier under .net, development, en
I’m using log4net 1.2.10 for a few month now and couldn’t ever get rid of it. Today I was playing with the udp appender: I was trying to have my application send logs via udp to Log4NetViewer… and nothing happened. After having enabled the log4net debug mode (1), I could see there was something wrong with the way log4net parsed my IP (2):
log4nelog4net:ERROR [UdpAppender] Unable to send logging event to remote host ::1 on port 1234.
System.Net.Sockets.SocketException: Une adresse incompatible avec le protocole demandé a été utilisée
à System.Net.Sockets.Socket.SendTo(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint remoteEP)
à System.Net.Sockets.UdpClient.Send(Byte[] dgram, Int32 bytes, IPEndPoint endPoint)
à log4net.Appender.UdpAppender.Append(LoggingEvent loggingEvent)
log4net was transforming my “192.168.0.2″ parameter IP into ::1, and the problem took place in the method IPAddressConverter.ConvertFrom() (the file is located under log4net-1.2.10\src\Util\TypeConverters\IPAddressConverter.cs).
The problem is that when compiled with .NET 2.0, the original code is returning the first IP address associated with the host (host itself returned by a dns lookup):
IPHostEntry host = Dns.GetHostEntry(str);
if (host != null &&
host.AddressList != null &&
host.AddressList.Length > 0 &&
host.AddressList[0] != null)
{
return host.AddressList[0];
}
When inspecting the content of this address list with the debugger I got:
+ [0] {::1} System.Net.IPAddress
+ [1] {192.168.0.2} System.Net.IPAddress
+ [2] {192.168.206.1} System.Net.IPAddress
+ [3] {192.168.114.1} System.Net.IPAddress
So, with the existing code, the address ::1 is selected… and the UdpAppender throws an exception
To avoid this:
first I added this property to IPAddressConverter:
public bool IsIPv6Supported { get { return false; } }
note that I’m not networking aware, and thus this may be replaced by some code able to detect wether or not IP v6 is supported…
then I replaced “return host.AddressList[0];” with:
foreach (IPAddress address in host.AddressList)
{
if ((address.AddressFamily ==
System.Net.Sockets.AddressFamily.InterNetworkV6) &&
!IsIPv6Supported)
continue;
return address;
}
This way, I return the first IPv4 address instead of the first address.Hope this helps
(1) to do so, just add the following xml to your app.config:
<appSettings>
<add key=“log4net.Internal.Debug“ value=“true“/>
</appSettings>
(2) aproximatively translated from French into English: The used address is incompatible with the requested protocol
PS: if you want to compile the log4net visual studio project provided with the distribution, you have to apply these guidelines: http://logging.apache.org/log4net/release/building.html#vsnet-2005
17/04/2007 at 20:53
Thank You
13/02/2008 at 14:45
Thanks for this post - I’ve been struggling with exactly the same issue - which is slightly disappointing given that it’s a year since you posted this. It otherwise renders UdpAppenders an exercise in frustration. Possibly a better solution would be to add a line after the foreach to return an IPv6, which would give a fallback if a system happened to be configured as IPv6 only?
19/02/2008 at 23:45
You are right, in an algorthmic point of view, this is a bug in a only-IPV6 configuration.
But better than it, I should test the corrections provided by the log4net team (classes UdpAppender and IPAddressConverter).
In substance, the IP parsing has been corrected by adding a check.
And, if compiled with .NET 2, the AddressFamily is passed to the UdpAppender’s underlying UdpClient upon creation.