Bug 23052
Summary: | pump fails on dual NIC machine | ||||||
---|---|---|---|---|---|---|---|
Product: | [Retired] Red Hat Linux | Reporter: | Need Real Name <mike> | ||||
Component: | pump | Assignee: | Elliot Lee <sopwith> | ||||
Status: | CLOSED CURRENTRELEASE | QA Contact: | David Lawrence <dkl> | ||||
Severity: | medium | Docs Contact: | |||||
Priority: | medium | ||||||
Version: | 7.0 | CC: | icote, mike, mike, ml, olivier.baudron | ||||
Target Milestone: | --- | ||||||
Target Release: | --- | ||||||
Hardware: | i386 | ||||||
OS: | Linux | ||||||
Whiteboard: | |||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||
Doc Text: | Story Points: | --- | |||||
Clone Of: | Environment: | ||||||
Last Closed: | 2004-06-28 16:13:31 UTC | Type: | --- | ||||
Regression: | --- | Mount Type: | --- | ||||
Documentation: | --- | CRM: | |||||
Verified Versions: | Category: | --- | |||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
Cloudforms Team: | --- | Target Upstream Version: | |||||
Embargoed: | |||||||
Attachments: |
|
Description
Need Real Name
2000-12-31 05:10:43 UTC
I can confirm this problem is still in RHL 7.1 (and current rawhide). In the relatively common firewall type configuration of a dual-homed machine with one public and one private addr, with the public one set by DHCP, if the private interface already has an addr configured, pump will send out its request on the public interface with the private addr as the source address. Given that these private addresses are frequently 10.*.*.* or 172.16.*.* addresses, some DHCP servers will refuse to listen to these requests. When dhcpcd kicks in when pump fails, it all works because it correctly uses a source address of 0.0.0.0. The problem in the code is the following: dhcp.c: 1009 memset(&clientAddr.sin_addr, 0, sizeof(&clientAddr.sin_addr)); clientAddr.sin_family = AF_INET; clientAddr.sin_port = htons(BOOTP_CLIENT_PORT); /* bootp client */ if (bind(s, (struct sockaddr *) &clientAddr, sizeof(clientAddr))) { This does *not* set the IP source adress to 0.0.0.0 Indeed, as is said in the Stevens (page 92), when binding the socket, we can specify a wildcard that lets the kernel choose the adress. This wildcard is the constant INADDR_ANY. And unfortunately, this constant is 0.0.0.0. So, the kernel choose the IP source address on its own, and I suppose it is the first interface it finds. If there is no bug in the kernel in doing this, the only solution to fix the problem id to use a raw socket instead, and reimplement udp/ip, as is done in dhcpcd. Created attachment 22246 [details]
patch to fix 0.0.0.0 source adress issue with multiple NICs
First I have a question: in dhcp.c:pumpDhcpRun(), why the socket is not created with createSocket()? Is there any good reason for this? Next, I have noticed, that in its own building socket instructions, pumpDhcpRun() does not set SO_BINDTODEVICE before binding the device to the 0.0.0.0 adress. So, it is probable that if other interfaces are already running, the kernel set one of these ip adresses as source. The attached patch (above) should fix the problem. Argh, I just got a 2nd NIC, and tried my patch .... it does not work! Well, there might be a problem with the kernel: it is possible to send 0.0.0.0 source udp packet only if all interfaces are down. I tried the patch and I'm afraid it doesn't work. I investigated a bit closer in the kernel to see what it does. Fundamentally it all depends on the function inet_select_addr(). And I can't see any way to force an address of 0.0.0.0. But I'm not a kernel expert and may have traced it through incorrectly. There's a lot of hairy stuff here. Well... I'm afraid raw sockets are necessary at this point. Unless a kernel expert can tell us a trick for this issue? ;) I am the original poster of this bug, but my e-mail address has changed to mike. Although I'm not currently a programmer, I am learning. If there is something I can assist with, please feel free to contact me. In rawhide, pump is obsoleted by dhcpcd, which I know does its own packet construction, and I'm pretty sure that it is more RFC-compliant. :) pump is still used in the installer though, so if this problem occurs at install time, maybe a solution is possible after all with the info you have given. *** Bug 23477 has been marked as a duplicate of this bug. *** *** Bug 27492 has been marked as a duplicate of this bug. *** Well... I must have missed something. Mike opened a bug report and said "pump fails with a dual nic PC, and the reason may be this one". Then several people made some tests, and finally the conclusion was: "Mike, you're right, there is a bug in the pump code at lines there and there" Then come redhat people... who said "fine guys, if you don't use pump anymore, it should work. So let's close this bug and be happy". So, why doesn't redhat leave this bug open??? Else, what more info do you *need* ??? The problem with dhcpcd is that it is that it is 401096 bytes in size. Since pump weighs in at 46256 bytes, it fits much better on the bootable floppy I created for routing / masq / packet filtering. Please forgive me if this is blatantly wrong (after all, I am new to programming)...But couldn't bind() be called before calling connect() in order to set the source address to 0.0.0.0? One thing that might be a problem is where Stevens says (bottom of p.91), "A process can bind a specific IP address to its socket. The ip address must belong to an interface on the host. For a TCP client, this assigns the source IP address that will be used for IP datagrams sent on the socket." So, the question is: Since the interface is down, does it have an IP address at all? If not, how do you assign 0.0.0.0 to a socket when 0.0.0.0 doesn't belong to any interfaces on the host. Another thought: Could it be possible to bring up the interface initially with 0.0.0.0 as the address? That way, this address would belong to an interface on the host and could then be used by bind() as a source address for the socket? Just my $.02 * There is no need for connect() before sending datas on an udp socket. * The intercace is not down. At the beginning, pump activates the interface in pumpPrepareInterface(), and in particular, it sets its IP adress to 0.0.0.0 (at least, it tries), and set some flags (one of them says the interface is up). Also, I traced in the program and noticed that setting the IP adress to 0.0.0.0 has no effect: after the ioctl() call, ifconfig shows that no IP adress is assigned to the interface. This is again a problem with the special 0 value, since replacing this by anything else works (as is shown with ifconfig). => So the main problem is that ioctl(s, SIOCSIFADDR, &req) does not work with the ip adress 0.0.0.0. *** Bug 53700 has been marked as a duplicate of this bug. *** *** Bug 77802 has been marked as a duplicate of this bug. *** |