Log4Net: IP parsing bug when used with framework .NET 2.0
Posted by Olivier on 13/01/2007
Update (2008/08/21):
As stated by SergeS in his comment, the solution I provide below (while working) should not be used any more. Instead, replace your src/Appender/UdpAppender.cs file with the one found here:
https://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/UdpAppender.cs?revision=506603
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
Mark said
Thank You
David said
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?
Olivier said
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.
SergeS said
Problem is not with IPAddressConverter.
All you need is fix two lines in ‘UdpAppender::InitializeClientConnection()’, so that both ‘new UdpClient()’ calls use ‘RemoteEndPoint.AddressFamily’ parameter as well.
With this fix both IP4 and IP6 working OK.
Olivier said
Thank you SergeS!
Just after having read your comment I checked the log4net repository and jira (https://issues.apache.org/jira/browse/LOG4NET-112). And the source code has been modified in the same way that your proposition.
Using LogView4Net with EPiServer | Fredrik Haglund's blog said
[...] appears that there is are issues in net 2.0 with IPv6 interfering with the parsing of the remoteAddress but the bug fix appear not to [...]
The devva.net blog | log4net UdpAppender on IPv6 (Windows 2008, Vista or 7) said
[...] at least) and that is something that didn't make it into the log4net 1.2.10 release. There are some fixes to log4net, but the 1.2.10 version is compiled into loads of other framworks that I'm using and compiling an [...]
Gbps [Michael Frohlich] said
Hey, thanks a bunch for this! Took 30 minutes of useless googleing until I found this gold mine!
inventory software said
i have seen your post. i like it want to learn more about your post