Linux, IO::Socket::INET and recv'ing broadcasted UDP


D

DJ Stunks

Hey all, it's been a while since I hung out here but I still use Perl
from time to time (and miss using it!).

Anyway, I originally posted this question at comp.lang.perl.modules
but I'm not getting any responses and I'm not sure it's a modules
question anyway - maybe more a socket/Linux problem.

Original post here (includes code):

http://groups.google.com/group/comp.lang.perl.modules/msg/8ce530096fe7fdac?

In summary, I'm attempting to use Net::DHCP::packet and
IO::Socket::INET to generate, transmit and receive DHCP messages
(discover, offer, request, ack). The problem is that I'm not able to
use the IO::Socket recv method to receive a broadcasted DHCP offer
packet. My script blocks indefinitely though I see the offer arrive
via Wireshark.

I'm following the example from the Net::DHCP::packet package and, in
Googling, no one else mentions issues with this. Therefore I assume
that the error is on my part - probably a simple error - but I don't
know enough to diagnose it.

As I mentioned, I'm using Linux with eth0 set up with a static IP
(10.0.0.1). I was not able to set the interface to 0.0.0.0 as I'd
assumed I should in order to perform DHCP transactions.

I'm open to any and all suggestions, tips, etc.

Thanks in advance,
-jp
 
Ad

Advertisements

B

Ben Morrow

Quoth DJ Stunks said:
Hey all, it's been a while since I hung out here but I still use Perl
from time to time (and miss using it!).

Anyway, I originally posted this question at comp.lang.perl.modules
but I'm not getting any responses and I'm not sure it's a modules
question anyway - maybe more a socket/Linux problem.

Original post here (includes code):

http://groups.google.com/group/comp.lang.perl.modules/msg/8ce530096fe7fdac?

In summary, I'm attempting to use Net::DHCP::packet and
IO::Socket::INET to generate, transmit and receive DHCP messages
(discover, offer, request, ack). The problem is that I'm not able to
use the IO::Socket recv method to receive a broadcasted DHCP offer
packet. My script blocks indefinitely though I see the offer arrive
via Wireshark.

In that message, you wrote:
|
| #open socket for packet tx & rx
| my $socket = IO::Socket::INET->new( Proto => 'udp',
| Broadcast => 1,
| LocalAddr => '10.0.0.1',
| LocalPort => 68,
| PeerAddr => '255.255.255.255',
| PeerPort => 67,
| ) || die "Unable to create socket: [email protected]\n";
|
| my $discover = Net::DHCP::packet->new(
| Xid => int rand(0xFFFFFFFF),
| Chaddr => 00011aabbccd,
| DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
| DHO_VENDOR_CLASS_IDENTIFIER() => 'MyVendorClassID',
| DHO_DHCP_PARAMETER_REQUEST_LIST() => '1 2 6 12 15 28 67',
| );

RFC 2131 says "If the broadcast bit is not set and 'giaddr' is zero and
'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK
messages to the client's hardware address and 'yiaddr' address.". That
applies here, so the packet will not be broadcast, it will be sent as a
unicast Ethernet frame to your claimed hardware address
(00:01:1a:ab:bc:cd) with an IP packet addressed to your claimed IP addr
(0.0.0.0, since you didn't set yiaddr) inside.

Even if this packet gets to you (are you using your real hardware
address?) you can't read such a packet from an IP socket under Linux.
You need to put the interface in promiscuous mode (which requires root)
and use a PF_PACKET socket with an appropriate filter to get hold of the
packet. See e.g. setup_packet_filters, open_socket and get_packet in
http://git.marples.name/?p=dhcpcd/.git;a=blob;f=socket.c (make sure you
read the #ifdef __linux__ version).

Alternatively, you could try setting Flags => 1, which asks for the
reply to be broadcast (for the sake of clients whose IP stacks can't
cope with confusingly-addressed packets), in which case an ordinary UDP
socket should be able to pick it up.

Ben
 
D

DJ Stunks

Quoth DJ Stunks <[email protected]>:






In that message, you wrote:
|
| #open socket for packet tx & rx
| my $socket = IO::Socket::INET->new( Proto => 'udp',
| Broadcast => 1,
| LocalAddr => '10.0.0.1',
| LocalPort => 68,
| PeerAddr => '255.255.255.255',
| PeerPort => 67,
| ) || die "Unable to create socket: [email protected]\n";
|
| my $discover = Net::DHCP::packet->new(
| Xid => int rand(0xFFFFFFFF),
| Chaddr => 00011aabbccd,
| DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
| DHO_VENDOR_CLASS_IDENTIFIER() => 'MyVendorClassID',
| DHO_DHCP_PARAMETER_REQUEST_LIST() => '1 2 6 12 15 28 67',
| );

RFC 2131 says "If the broadcast bit is not set and 'giaddr' is zero and
'ciaddr' is zero, then the server unicasts DHCPOFFER and DHCPACK
messages to the client's hardware address and 'yiaddr' address.". That
applies here, so the packet will not be broadcast, it will be sent as a
unicast Ethernet frame to your claimed hardware address
(00:01:1a:ab:bc:cd) with an IP packet addressed to your claimed IP addr
(0.0.0.0, since you didn't set yiaddr) inside.

Even if this packet gets to you (are you using your real hardware
address?) you can't read such a packet from an IP socket under Linux.
You need to put the interface in promiscuous mode (which requires root)
and use a PF_PACKET socket with an appropriate filter to get hold of the
packet. See e.g. setup_packet_filters, open_socket and get_packet inhttp://git.marples.name/?p=dhcpcd/.git;a=blob;f=socket.c(make sure you
read the #ifdef __linux__ version).

Alternatively, you could try setting Flags => 1, which asks for the
reply to be broadcast (for the sake of clients whose IP stacks can't
cope with confusingly-addressed packets), in which case an ordinary UDP
socket should be able to pick it up.

Hi Ben,

Thanks for the reply.

The DHCP Offer I'm receiving is definitely addressed to destination IP
255.255.255.255:68 (perhaps my DHCP server is non-compliant?). I did
try setting Flags => 1 as one of my tests and it didn't make a
difference but I'll repeat it to be sure.

The Linux stuff is interesting. I'm not using my true hardware
address because the goal of the test is to check the DHCP behavior for
various hardware classes. Perhaps that's the problem. I'll go over
what you suggested and give it a try in the morning.

I wasn't able to set eth0 to 0.0.0.0 using ifconfig but you're right,
yiaddr is 0.0.0.0 within the discover payload.

-jp
 
D

DJ Stunks

Hey all, it's been a while since I hung out here but I still use Perl
from time to time (and miss using it!).

Anyway, I originally posted this question at comp.lang.perl.modules
but I'm not getting any responses and I'm not sure it's a modules
question anyway - maybe more a socket/Linux problem.

Original post here (includes code):

http://groups.google.com/group/comp.lang.perl.modules/msg/8ce530096fe...

In summary, I'm attempting to use Net::DHCP::packet and
IO::Socket::INET to generate, transmit and receive DHCP messages
(discover, offer, request, ack). The problem is that I'm not able to
use the IO::Socket recv method to receive a broadcasted DHCP offer
packet. My script blocks indefinitely though I see the offer arrive
via Wireshark.

I'm following the example from the Net::DHCP::packet package and, in
Googling, no one else mentions issues with this. Therefore I assume
that the error is on my part - probably a simple error - but I don't
know enough to diagnose it.

As I mentioned, I'm using Linux with eth0 set up with a static IP
(10.0.0.1). I was not able to set the interface to 0.0.0.0 as I'd
assumed I should in order to perform DHCP transactions.

I'm open to any and all suggestions, tips, etc.

Well, after Ben mentioned promiscuous mode I did some more Googling
and it turns out Abigail had problems with the same issue in 2004
(http://www.perlmonks.org/index.pl?node_id=325248).

So I feel a lot better if it can happen to him too ;-)

Abigail was on RH; I'm on Fedora. So now to figure out what was
blocked and how to unblock it. iptables? I'll check tomorrow but I
thought I tried with the thing wide open at least once...

-jp
 
D

DJ Stunks

Well, after Ben mentioned promiscuous mode I did some more Googling
and it turns out Abigail had problems with the same issue in 2004
(http://www.perlmonks.org/index.pl?node_id=325248).

So I feel a lot better if it can happen to him too ;-)

Abigail was on RH; I'm on Fedora. So now to figure out what was
blocked and how to unblock it. iptables? I'll check tomorrow but I
thought I tried with the thing wide open at least once...

Still no luck. Have tried with Flags => 1 in the IO::Socket::INET
constructor. The DHCPOFFER is broadcasted regardless (Ethernet
destination MAC = ff:ff:ff:ff:ff:ff; destination IP = 255.255.255.255;
destination udp port = 68) but my socket never receives it.

Have run with iptables completely flushed. Tried running the same
script on FreeBSD with the same results.

Does Abigail still hang out here? It sounds like he had an identical
issue...

Last thing to do: trying to set interface as promiscuous. Can I do it
from Perl? I tried ifconfig eth0 promisc before running the script,
but identical results.

Thanks,
-jp
 
B

Ben Morrow

Quoth DJ Stunks said:
Still no luck. Have tried with Flags => 1 in the IO::Socket::INET
constructor.

The Flags => 1 was in the Net::DHCP::packet constructor.
The DHCPOFFER is broadcasted regardless (Ethernet
destination MAC = ff:ff:ff:ff:ff:ff; destination IP = 255.255.255.255;
destination udp port = 68) but my socket never receives it.

That's... odd. Can you recieve other broadcast datagrams?

Have you tried using a PF_PACKET socket?

Ben
 
Ad

Advertisements

D

DJ Stunks

Quoth DJ Stunks <[email protected]>:




The Flags => 1 was in the Net::DHCP::packet constructor.

Right, my bad. I think I tried that too, but I'll repeat to be sure.
That's... odd. Can you recieve other broadcast datagrams?

Have you tried using a PF_PACKET socket?

I thought it was odd too, but I'm continuing to research (so
frustrated! ;-)) and I think what I'm finding is that it's not that
odd...

Here's a post from Solaris' bug tracker: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4191980.
The originator had a similar problem, but with Java. The response
was:

"The Solaris (& Linux for that matter) behavior is
that to be able to receive broadcasts a UDP socket has to be bound to
the
wildcard address (aka anylocal). This has been the defacto standard
behavior
since the days of BSD 4.3. Win32 behaviors differs from that. So the
only way
to be guaranteed to receive the broadcasts on any platform is to bind
to
the wildcard address."

So I tried changing my IO::Socket::INET constructor to use INADDR_ANY,
but no luck. The constructor seems to ignore PeerAddr => '0.0.0.0';

This page (http://wiki.forum.nokia.com/index.php/
How_to_use_udp_broadcast) shows how to set up a Python socket for UDP
broadcast.

So now my question is, how do I set up a Perl socket similarly? Can I
still use IO::Socket::INET to set PF_INET (is that the same as
PF_PACKET?) or do I have to use Socket instead?

As I'm sure everyone can tell, I'm out of my depth, but learning...
slowly.

Thanks Ben,
-jp
 
B

Ben Morrow

Quoth DJ Stunks said:
I thought it was odd too, but I'm continuing to research (so
frustrated! ;-)) and I think what I'm finding is that it's not that
odd...

Here's a post from Solaris' bug tracker:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4191980.
The originator had a similar problem, but with Java. The response
was:

"The Solaris (& Linux for that matter) behavior is that to be able to
receive broadcasts a UDP socket has to be bound to the wildcard
address (aka anylocal). This has been the defacto standard behavior
since the days of BSD 4.3. Win32 behaviors differs from that. So the
only way to be guaranteed to receive the broadcasts on any platform is
to bind to the wildcard address."

OK. I didn't know that, but it makes some sense.
So I tried changing my IO::Socket::INET constructor to use INADDR_ANY,
but no luck. The constructor seems to ignore PeerAddr => '0.0.0.0';

No, you need LocalAddr => '0.0.0.0'. It's the address of *this* socket
you're setting, not the address you're talking to. For UDP sockets,
PeerAddr sets the default destination for sends.
This page (http://wiki.forum.nokia.com/index.php/
How_to_use_udp_broadcast) shows how to set up a Python socket for UDP
broadcast.

Whoa... that page is about PyS60, otherwise known as 'Python for itty
bitty Symbian phones with rather weird network stacks' :). However, the
code they give is basically the same as on any other platform; here
(FreeBSD) I can send and recieve broadcast datagrams with

#!/usr/bin/perl -l

use warnings;
use strict;

use IO::Socket::INET;

use Data::Dump qw/dump/;

my $port = 8091;

if ($ARGV[0] eq 'recv') {
my $SCK = IO::Socket::INET->new(
Type => SOCK_DGRAM,
Proto => 'udp',
LocalAddr => '0.0.0.0',
LocalPort => $port,
Broadcast => 1,
) or die "socket: [email protected]";

$SCK->recv(my $buf, 512, 0)
or die "recv: [email protected] $!";

print dump $buf;
}
else {
my $SCK = IO::Socket::INET->new(
Type => SOCK_DGRAM,
Proto => 'udp',
PeerAddr => $ARGV[1],
PeerPort => $port,
Broadcast => 1,
) or die "socket: $!";

my $buf = 'Hello world!';
$SCK->send($buf)
or die "send: $!";
}

__END__

though I find I have to send to 192.168.1.255 (the local net broadcast
addr) rather than 255.255.255.255, which ought to be the same. I don't
know why that is.
So now my question is, how do I set up a Perl socket similarly? Can I
still use IO::Socket::INET to set PF_INET (is that the same as
PF_PACKET?) or do I have to use Socket instead?

No, PF_PACKET isn't the same as PF_INET. PF_INET is the normal Internet
protocol family: basically TCP or UDP over IP, though on most OSen you
can use PF_INET/SOCK_RAW sockets to talk any IP protocol, including
ICMP. In Perl you can use IO::Socket::INET to do anything your OS will
let you do with PF_INET sockets.

PF_PACKET is a Linux-specific protocol family for talking directly to
the network driver; it allows you to send and receive raw Ethernet
frames, for example. Perl has no IO::Socket support for PF_PACKET
(though writing an IO::Socket::pACKET wouldn't be too hard: it's mostly
just packing and unpacking the addresses, which is code you'd need to
write to use these sockets anyway), so if you need these you would have
to use the socket builtins (Socket wouldn't help, here, as that only has
AF_INET/AF_UNIX support).

Ben
 
M

mkparam

All

I know this is a pretty old thread, but looks like i hit the exact same problem this week while trying to use DHCP::packet.

My requirement is that i want to use this perl module to get the IP's from DHCP server to do some PoC. I have two VM's , one act as DHCP server (RHEL564bit), and another RHEL5 64bit to run this script to get IP's from the DHCP server , both having two interfaces eth0 and eth1; eth1 of both the VM'sconnected to a VMware VSwitch to isolate these two VM's from others; eth0 of both the VM's having a valid IP in the range 10.72.x.x ; DHCP server listens on eth1 from the first VM.

When i use a script like this one, i can see the DHCPDISCOVER is sent properly as it reaches the server and DHCPOFFER is also being made by the serveras per the logs ; but my script does not pick up the packet for some reasons which i am unable to understand.

--script --

#!/usr/bin/perl
# Simple DHCP client - sending a broadcasted DHCP Discover request

use IO::Socket::INET;
use Net::DHCP::packet;
use Net::DHCP::Constants;

use POSIX qw(setsid strftime);

# sample logger
sub logger{
my $str = shift;
print STDOUT strftime "[%d/%b/%Y:%H:%M:%S] ", localtime;
print STDOUT "$str\n";
}

logger("DHCPd tester - dummy client");

logger("Opening socket");
$handle = IO::Socket::INET->new(Proto => 'udp',
Broadcast => 1,
PeerPort => 67,
LocalPort => 68,
LocalAddr => '192.168.1.3',
PeerAddr => '255.255.255.255')
|| die "Socket creation error: [email protected]\n"; # yes, it uses [email protected] here

# create DHCP Packet DISCOVER
$discover = Net::DHCP::packet->new(
Xid => 0x12345678,
Flags => 1,
Chaddr => '0050569821A9',
DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
DHO_VENDOR_CLASS_IDENTIFIER() => 'foo',
);

logger("Sending DISCOVER to 192.168.1.2:67");
logger($discover->toString());
$handle->send($request->serialize())
or die "Error sending:$!\n";
logger("Waiting for response from server");
$handle->recv($buf, 4096) || die("recv:$!");
logger("Got response");
$response = new Net::DHCP::packet($buf);
logger($response->toString());

-- /var/log/messages of DHCP Server ---
Jul 26 22:21:03 vmlnx64-30 dhcpd: DHCPDISCOVER from 00:50:56:98:21:a9 via eth1
Jul 26 22:21:03 vmlnx64-30 dhcpd: DHCPOFFER on 192.168.1.49 to 00:50:56:98:21:a9 via eth1

** TCPDUMP of DHCP Server and Client when this is being run ***

DHCPSERVER
**********
dhcp-Server>tcpdump -i eth1 -vvv
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
17:40:27.555097 IP (tos 0x0, ttl 1, id 0, offset 0, flags [none], proto: IGMP (2), length: 36, options ( RA (148) len
4 )) 10.0.0.0 > all-systems.mcast.net: igmp query v3 [max resp time 1s]
17:40:27.634538 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4
)) 192.168.1.2 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr 224.0.0.251 is_ex { }]
17:40:33.120044 IP (tos 0x0, ttl 64, id 2290, offset 0, flags [DF], proto:UDP (17), length: 328) 192.168.1.3.bootpc >
255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:56:98:23:8d (oui Unknown), length: 300, xid:0x12345678, flags: [none] (0x0000)
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:40:33.121657 arp who-has 192.168.1.50 tell 192.168.1.2
17:40:34.001555 IP (tos 0x10, ttl 16, id 0, offset 0, flags [none], proto:UDP (17), length: 328) 192.168.1.2.bootps > 192.168.1.50.bootpc: BOOTP/DHCP, Reply, length: 300, xid:0x12345678, flags: [none] (0x0000)
Your IP: 192.168.1.50
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:40:34.122468 arp who-has 192.168.1.50 tell 192.168.1.2
17:40:34.554985 IP (tos 0x0, ttl 1, id 0, offset 0, flags [none], proto: IGMP (2), length: 36, options ( RA (148) len 4 )) 10.0.0.0 > all-systems.mcast.net: igmp query v3 [max resp time 1s]
17:40:34.585378 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 192.168.1.2 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr 224.0.0.251 is_ex { }]
17:40:35.122279 arp who-has 192.168.1.50 tell 192.168.1.2
17:41:06.957198 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:06.957210 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:06.957211 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:06.957223 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:07.556639 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:07.630083 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 192.168.1.3 > igmp.mcast.net: igmp v3 report, 1 group record(s) [
gaddr 224.0.0.251 is_ex { }]
17:41:08.558188 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:09.557206 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:09.706661 IP (tos 0x0, ttl 64, id 38874, offset 0, flags [DF], proto: UDP (17), length: 328) 192.168.1.3.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:56:98:23:8d (oui Unknown), length: 300, xid:0x12345678, flags: [none] (0x0000)
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:41:09.706840 IP (tos 0x10, ttl 16, id 0, offset 0, flags [none], proto:UDP (17), length: 328) 192.168.1.2.bootps > 192.168.1.50.bootpc: BOOTP/DHCP,
Reply, length: 300, xid:0x12345678, flags: [none] (0x0000)
Your IP: 192.168.1.50
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:41:11.556846 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:14.557189 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:14.643834 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 192.168.1.3 > igmp.mcast.net: igmp v3 report, 1 group record(s) [
gaddr 224.0.0.251 is_ex { }]
17:41:19.557221 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:27.559216 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)
17:41:40.558913 rarp who-is 00:50:56:98:23:8d (oui Unknown) tell 00:50:56:98:23:8d (oui Unknown)


DHCP CLIENT
***********
dhcp-Client>tcpdump -i eth1 -vvv
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
17:41:07.553418 IP (tos 0x0, ttl 1, id 0, offset 0, flags [none], proto: IGMP (2), length: 36, options ( RA (148) len 4 )) 10.0.0.0 > all-systems.mcast.net: igmp query v3 [max resp time 1s]
17:41:07.626696 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 192.168.1.3 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr 224.0.0.251 is_ex { }]
17:41:09.703284 IP (tos 0x0, ttl 64, id 38874, offset 0, flags [DF], proto: UDP (17), length: 328) 192.168.1.3.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:56:98:23:8d (oui Unknown), length: 300, xid:0x12345678, flags: [none] (0x0000)
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:41:09.703796 IP (tos 0x10, ttl 16, id 0, offset 0, flags [none], proto:UDP (17), length: 328) 192.168.1.2.bootps > 192.168.1.50.bootpc: BOOTP/DHCP, Reply, length: 300, xid:0x12345678, flags: [none] (0x0000)
Your IP: 192.168.1.50
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:41:14.553952 IP (tos 0x0, ttl 1, id 0, offset 0, flags [none], proto: IGMP (2), length: 36, options ( RA (148) len 4 )) 10.0.0.0 > all-systems.mcast.net: igmp query v3 [max resp time 1s]
17:41:14.640463 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 192.168.1.3 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr 224.0.0.251 is_ex { }]
17:41:21.554244 rarp who-is 00:50:56:98:04:36 (oui Unknown) tell 00:50:56:98:04:36 (oui Unknown)

There is no iptables as i can verify.

Any help to figure out why my script unable to receive the DHCP Offer Packets(that has the Your_IP details )would be much appreciated. Thanks for the help.


PK
 
P

Peter J. Holzer

All

I know this is a pretty old thread, but looks like i hit the exact
same problem this week while trying to use DHCP::packet. [...]
When i use a script like this one, i can see the DHCPDISCOVER is sent
properly as it reaches the server and DHCPOFFER is also being made by
the server as per the logs ; but my script does not pick up the packet
for some reasons which i am unable to understand.

--script -- [...]
$handle = IO::Socket::INET->new(Proto => 'udp',
Broadcast => 1,
PeerPort => 67,
LocalPort => 68,
LocalAddr => '192.168.1.3',
PeerAddr => '255.255.255.255')
|| die "Socket creation error: [email protected]\n"; # yes, it uses [email protected] here [...]
17:41:09.706661 IP (tos 0x0, ttl 64, id 38874, offset 0, flags [DF], proto: UDP (17), length: 328) 192.168.1.3.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:56:98:23:8d (oui Unknown), length: 300, xid:0x12345678, flags: [none] (0x0000)
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]
17:41:09.706840 IP (tos 0x10, ttl 16, id 0, offset 0, flags [none], proto: UDP (17), length: 328) 192.168.1.2.bootps > 192.168.1.50.bootpc: BOOTP/DHCP,
Reply, length: 300, xid:0x12345678, flags: [none] (0x0000)
Your IP: 192.168.1.50
Client Ethernet Address: 00:50:56:98:23:8d (oui Unknown) [|bootp]

I guess this is the reason: You are sending the request from 192.168.1.3
and have bound the socket to this address. But the answer is sent to
192.168.1.50, so you won't receive it. Binding to 0.0.0.0 may help, but
I doubt it: If you currently don't have the address 192.168.1.50, I
think the kernel is supposed to discard the packet. You may have to use
a raw socket.

hp
 
M

mkparam

Thank you Ben and Peter for your replies. Now my comments specific to your ideas ..

#1 I did check the promiscuous mode before replying and it was indeed open and i got it open through the 'ip link' for the interface too, but those did not help. Since I was able to see the packets floating in the tcpdump at the server and client i believed that the issue is with the script only andindeed it was.
#2 when i set the 'PeerAddr' to 0.0.0.0, it did not help so i reverted backto my client eth1 IP.
#3 I changed the PeerPort and LocalPort to '67'
#4 I checked the dhclient and it got the ip from my server so if that can work and my script can't , proves a point that the script has an issue. Later i played around in the script and got it working..

Now my script looks like this
.....
$handle = IO::Socket::INET->new(Proto => 'udp',
Broadcast => 1,
PeerPort => 67,
LocalPort => 67,
PeerAddr => '192.168.1.2')
|| die "Socket creation error: [email protected]\n"; # yes, it uses [email protected] here

# create DHCP Packet DISCOVER
$discover = Net::DHCP::packet->new(
op=> BOOTREQUEST(),
Htype => '0',
Hlen => '6',
Ciaddr => '0',
Chaddr => $MAC,
Giaddr => $handle -> sockhost(),
Xid => int(rand(0xFFFFFFFF)),
DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
);
....

Now, I receive the IP's from the client and i can read the packet as i wanted , works GREAT !!

But, a new challenge, I noticed that every time i send the 'DHCPREQUEST' , my client gets a new IP though i pass on a hard-coded mac-address(MAC1 as an argument to pass on with different MACs for my try's) in the script. Server reads this MAC but rather than throwing an IP that was already given (per leases, its not expired) it gives a new IP. Is this expected ?

Now questions ..

1. Are there any settings in the dhcpd.conf that has to explicitly say to look for leases before giving new Ip's?
2. How do i determine if the server has a valid lease for the mac i am sending before i can initiate a DHCPREQUEST ? ( Since i m scripting i want to make sure that for a particular mac , server gives the IP as per the lease if it is not expired and if it is let it renew rather than giving a new valid lease with a different IP. makes sense ? ) ; I came across 'DHCPLEASEQUERY' and realized (may be) it is not supported in 3.0.5 dhcpd version i am using ? I have told the support to upgrade to dhcp3.1 on RHEL5.

My requirement is like : <script> MAC which has to talk to my server , getsa IP if it has not having a valid lease . if new, get the IP and mark a lease. I am OK to check if it has a valid lease before placing a DHCPREQUEST but just not sure how i can do(what type of DHO_DHCP_MESSAGE_TYPE does that? )

Param
 
Ad

Advertisements

M

mkparam

I am back again. I upgraded the dhcp server to 4.1.11 on RHEL6 and the LEASEQUERY works great now.

perl inform.pl 192.168.1.2 192.168.1.14
marshall: packet too small (286), minimum size is 300 at inform.pl line 34
op = BOOTREPLY
htype = HTYPE_ETHER
hlen = 6
hops = 0
xid = 95aba24
secs = 0
flags = 0
ciaddr = 192.168.1.14
yiaddr = 0.0.0.0
siaddr = 0.0.0.0
giaddr = 192.168.1.3
chaddr = 005056aabbcc
sname =
file =
Options :
DHO_DHCP_MESSAGE_TYPE(53) = DHCPLEASEACTIVE
DHO_DHCP_SERVER_IDENTIFIER(54) = 192.168.1.2
DHO_DHCP_LEASE_TIME(51) = 1531
DHO_SUBNET_MASK(1) = 255.255.255.0
DHO_ROUTERS(3) = 192.168.1.0
DHO_DHCP_RENEWAL_TIME(58) = 31
DHO_DHCP_REBINDING_TIME(59) = 1156
DHO_CLIENT_LAST_TRANSACTION_TIME(91) = \x00\x00\x05\xBD
padding [0] =

Interestingly, I am unable to RENEW that IP to extend the lease. I am stillto crack this. If i can achieve the RENEW and RELEASE methods, i am all done since i would be able to successfully mimic the end-to-end dhcp cycle sothat my script can handle whatever is required according to the scenario. Any pointers ? DHCPRENEW is not accepted DHCP message type, and i found DHCPFORCERENEW is, but it fails, may be i am yet to understand how i must passthat to the server. Let me know if you guys have tried this before ? Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top