added dhcp scripts
This commit is contained in:
parent
00530f7f44
commit
6560762504
1 changed files with 640 additions and 0 deletions
640
dhcp/gendhcp.pl
Executable file
640
dhcp/gendhcp.pl
Executable file
|
@ -0,0 +1,640 @@
|
|||
#! /usr/bin/perl
|
||||
#
|
||||
# File: gendhcp.p
|
||||
# Author: Darin Davis, Copyright 1998
|
||||
# Date: 19 January 1998
|
||||
# Update: 28 October 1998
|
||||
# Desc: gendhcp.p is designed to test the ability of a DHCP server
|
||||
# to respond to a large number of DHCP client requests submitted
|
||||
# in rapid succession. Each DISCOVER message contains a unique:
|
||||
#
|
||||
# - Hardware address (CHADDR), beginning with '0fffffff'
|
||||
# and ending with a unique 16-bit number (starting by
|
||||
# default with 1).
|
||||
# - Client ID, identical to the hardware address
|
||||
# - XID, beginning with 'eeee' and ending with the same
|
||||
# ending number as the hardware address
|
||||
# - Hostname, beginning with 'dhcp-client-' and ending
|
||||
# with the same ending number as the hardware address
|
||||
# except in decimal rather than hex
|
||||
#
|
||||
# The script logic can be outlined as follows:
|
||||
#
|
||||
# 1 - Blast out all the DISCOVER msgs and optionally wait a
|
||||
# user-specified number of seconds to give the server a chance
|
||||
# to respond.
|
||||
#
|
||||
# 2 - Send REQUESTS for all the OFFERs in my input socket.
|
||||
#
|
||||
# 3 - Make note of any ACKs I receive.
|
||||
#
|
||||
# 4 - If I haven't received all the OFFERs, then resend DISCOVERs
|
||||
# for each DISCOVER as yet unOFFERed and optionally wait a
|
||||
# user-specified number of seconds to give the server a chance
|
||||
# to respond and go to step 2.
|
||||
#
|
||||
# 5 - If I have received all the OFFERs but not all the ACKs, then
|
||||
# resend a DISCOVER for each ACK I am missing and go to step 2.
|
||||
# Note that this is a departure from the RFC which suggests the
|
||||
# client should reREQUEST not reDISCOVER. But the implementation
|
||||
# was simpler this way.
|
||||
#
|
||||
# When the reDISCOVER is performed, the same XID is used.
|
||||
# This can cause problems for later versions of the QIP DHCP
|
||||
# server which have a configuration parameter "CheckTransactionID".
|
||||
# This parameter defaults to TRUE, meaning that the server will
|
||||
# not issue an address for a previously detected Transaction ID
|
||||
# (XID)/MAC address tuple. To suppress this behavior, set the
|
||||
# "CheckTransactionID" policy to FALSE by putting the following
|
||||
# into the dhcpd.pcy file:
|
||||
#
|
||||
# CheckTransactionID=0
|
||||
#
|
||||
# Thanks to Gary DiFazio for providing this information about QIP.
|
||||
#
|
||||
# There are no timeouts in the script. Only the optional wait.
|
||||
#
|
||||
# gendhcp.p simulates the four packet exchange DISCOVER-OFFER-
|
||||
# REQUEST-ACK, and maintains two associative arrays, one for
|
||||
# outstanding OFFERs and one for outstanding ACKs. The arrays
|
||||
# are indexed by the CHADDR of the DISCOVER packet. gendhcp.p
|
||||
# first blasts out all the DISCOVER messages, noting the CHADDRs
|
||||
# in the Offers and Acks arrays, and then goes into a loop waiting
|
||||
# for responses. If it receives an OFFER, it sends a REQUEST and
|
||||
# deletes the CHADDR from the Offers array. If it receives an ACK,
|
||||
# it deletes the CHADDR from the Acks array. If there are no
|
||||
# responses from a server to read but there are still outstanding
|
||||
# OFFERs or ACKs, it reDISCOVERS everything in the Offers array (or
|
||||
# if empty, the Acks array). It continues this process until all
|
||||
# ACKs have been received.
|
||||
#
|
||||
# Some DHCP servers send their OFFER messages to the IP broadcast
|
||||
# address. Others (such as NTS IPserver) address the OFFER to the
|
||||
# IP address which it is offering. Because the OFFER is not
|
||||
# addressed to the machine on which you run gendhcp.p, gendhcp.p
|
||||
# can't receive the offer. So, to test a server of the latter
|
||||
# variety, use the '-r' option. This puts gendhcp.p in "relay
|
||||
# agent" mode. It puts your machine's address in the GIADDR field,
|
||||
# convincing the unsuspecting DHCP server that your machine is
|
||||
# actually a router. So, the DHCP server addressees the OFFER to
|
||||
# your machine.
|
||||
#
|
||||
# The author used tcpdump (on the same machine as gendhcp.p) in
|
||||
# attempt to measure the effectiveness of the script. tcpdump
|
||||
# didn't capture all the packets sent and received. Therefore,
|
||||
# you would do well to use a standalone Sniffer-like device for
|
||||
# any tracing.
|
||||
#
|
||||
# gendhcp.p is intended for testing a single DHCP server. If
|
||||
# multiple DHCP servers are active, gendhcp.p will REQUEST only
|
||||
# one IP address for a given hardware address (just as a normal
|
||||
# DHCP client would).
|
||||
#
|
||||
# Developed for Linux with modifications for Solaris.
|
||||
#
|
||||
# Usage: See &usage().
|
||||
|
||||
|
||||
########################
|
||||
### GLOBAL CONSTANTS ###
|
||||
########################
|
||||
|
||||
# define which OS this is
|
||||
if (system("test `uname` = SunOS") == 0) {
|
||||
$OS = "SunOS";
|
||||
}
|
||||
else { $OS = "Linux" }
|
||||
#print "OS = $OS\n";
|
||||
|
||||
$AF_INET = 2; # define address family
|
||||
|
||||
if ($OS eq "Linux") { # Linux-specific definitions
|
||||
$SOCK_DGRAM = 2; # define socket type
|
||||
$SO_BROADCAST = 6;
|
||||
$SOL_SOCKET = 1;
|
||||
}
|
||||
else { # Solaris-specific definitions
|
||||
$SOCK_DGRAM = 1; # define socket type
|
||||
$SO_BROADCAST = 32;
|
||||
$SOL_SOCKET = 65535;
|
||||
}
|
||||
|
||||
$SOCKADDR_FMT = 'S n a4 x8'; # set pack format
|
||||
$DHCP_SERVER_PORT = 67;
|
||||
$DHCP_CLIENT_PORT = 68;
|
||||
$MAX_LEN = 1024; # max length of datagram
|
||||
$FLAGS = 0; # flags for recv()
|
||||
$DISC_MAX = 65000; # maximum number of discover msgs
|
||||
# to be generated
|
||||
$INADDR_ANY = pack("C4", split(/\./, "0.0.0.0"));
|
||||
$SO_RCVBUF = 8;
|
||||
$OPT_VAL = 1;
|
||||
$TRUE = 1 == 1;
|
||||
$DISC_MSG = 1;
|
||||
$OFFER_MSG = 2;
|
||||
$RQST_MSG = 3;
|
||||
$ACK_MSG = 5;
|
||||
$DELAY_MAX = 10; # limit on how long to wait before
|
||||
# reading server replies
|
||||
|
||||
|
||||
########################
|
||||
### GLOBAL VARIABLES ###
|
||||
########################
|
||||
|
||||
$Server_hostname = "255.255.255.255"; # default name of server host
|
||||
$Server_pport; # packed remote port number
|
||||
@Server_ipaddr; # server's IP address
|
||||
@Client_ipaddr; # my IP address
|
||||
*CS; # descriptor of socket bound to
|
||||
# local DHCP client port
|
||||
*SS; # descriptor of socket bound to
|
||||
# local DHCP server port
|
||||
$Protocol_name; # name of UDP protocol
|
||||
$Protocol_aliases; # aliases of UDP
|
||||
$Protocol_number; # UDP's protocol number
|
||||
$Addr_family; # client's address family
|
||||
$Discover_count = 1; # number of discover msgs to send
|
||||
$Datagram; # server's reply message
|
||||
$Suppress_request = ! $TRUE; # DO send requests
|
||||
$Offer_cnt = 0; # number of OFFERs received
|
||||
$Ack_cnt = 0; # number of ACKs received
|
||||
$Relay = ! $TRUE; # boolean flag: should I act like a
|
||||
# BOOTP relay agent (by listening
|
||||
# for offers on the BOOTPS port)?
|
||||
$Haddr = 1; # initial hardware address suffix
|
||||
$Rc; # Return Code for system calls
|
||||
%Offers; # outstanding (unreceived) OFFER msgs
|
||||
%Acks; # outstanding (unreceived) ACK msgs
|
||||
@Start_times; # user, system and elapsed start times
|
||||
@End_times; # user, system and elapsed end times
|
||||
$Delay = 0; # how long to wait before trying to
|
||||
# read replies from server
|
||||
$Retry = 0; # how many times we have to reDISCOVER
|
||||
$Last_ack_cnt = 0; # last count of ACKs received
|
||||
$Progress = ! $TRUE; # boolean flag: should I show the
|
||||
# number of ACKs received?
|
||||
|
||||
###################
|
||||
### SUBROUTINES ###
|
||||
###################
|
||||
|
||||
#####################################
|
||||
# defines functions needed to set
|
||||
# socket to non-blocking using fcntl
|
||||
#####################################
|
||||
sub F_SETFL {4;}
|
||||
|
||||
if ($OS eq "Linux") { # Linux-specific definition
|
||||
sub O_NONBLOCK {04000;}
|
||||
}
|
||||
else { # Solaris-specific definition
|
||||
sub O_NONBLOCK {0x80;}
|
||||
}
|
||||
|
||||
######################################
|
||||
# creates socket and binds to
|
||||
# DHCP client port
|
||||
# GLOBAL VARS: Server_hostname,
|
||||
# Server_pport, Client_ipaddr, CS, SS
|
||||
######################################
|
||||
sub setup_socket {
|
||||
local($client_hostname, # name of this host
|
||||
$client_pport # packed local port number
|
||||
);
|
||||
|
||||
chop($client_hostname = `hostname`); # get my hostname
|
||||
|
||||
# get UDP's protocol number
|
||||
($Protocol_name,$Protocol_aliases,$Protocol_number) = getprotobyname('udp');
|
||||
|
||||
# get my IP address
|
||||
($Protocol_name,$Protocol_aliases,$type,$len,@Client_ipaddr) = gethostbyname($client_hostname);
|
||||
|
||||
# get server's IP address
|
||||
($Protocol_name,$Protocol_aliases,$type,$len,@Server_ipaddr) = gethostbyname($Server_hostname);
|
||||
|
||||
# define fully-specified port addrs
|
||||
$client_pport = pack($SOCKADDR_FMT, $AF_INET, $DHCP_CLIENT_PORT, $INADDR_ANY);
|
||||
$Server_pport = pack($SOCKADDR_FMT, $AF_INET, $DHCP_SERVER_PORT, $Server_ipaddr[0]);
|
||||
|
||||
# create UDP socket
|
||||
socket(CS, $AF_INET, $SOCK_DGRAM, $Protocol_number) ||
|
||||
die("$0: cannot create CS socket ($!)");
|
||||
|
||||
# set socket to non-blocking
|
||||
($Rc = fcntl(CS, &F_SETFL, &O_NONBLOCK)) ||
|
||||
printf("error (%d) setting CS to non-blocking\n", $Rc);
|
||||
|
||||
|
||||
# enable send/recv broadcasts
|
||||
$Rc = setsockopt(CS, $SOL_SOCKET, $SO_BROADCAST, $OPT_VAL);
|
||||
if (! defined($Rc)) { print "error calling setsockopt(SO_BROADCAST) for CS\n"; }
|
||||
|
||||
# bind to the socket
|
||||
bind(CS, $client_pport) || die("$0: cannot bind CS socket to DHCP client port ($!)");
|
||||
|
||||
# setup extra socket in case we
|
||||
# have to act as the relay agent
|
||||
if ($Relay) {
|
||||
$client_pport = pack($SOCKADDR_FMT, $AF_INET, $DHCP_SERVER_PORT, $INADDR_ANY);
|
||||
|
||||
# create UDP socket
|
||||
socket(SS, $AF_INET, $SOCK_DGRAM, $Protocol_number) ||
|
||||
die("$0: cannot create SS socket ($!)");
|
||||
|
||||
# set socket to non-blocking
|
||||
($Rc = fcntl(SS, &F_SETFL, &O_NONBLOCK)) ||
|
||||
printf("error (%d) setting SS to non-blocking\n", $Rc);
|
||||
|
||||
# enable send/recv broadcasts
|
||||
$Rc = setsockopt(SS, $SOL_SOCKET, $SO_BROADCAST, $OPT_VAL);
|
||||
if (! defined($Rc)) { print "error calling setsockopt(SO_BROADCAST) for SS\n"; }
|
||||
|
||||
# bind to the socket
|
||||
bind(SS, $client_pport) || die("$0: cannot bind SS socket to DHCP server port ($!)");
|
||||
}
|
||||
}
|
||||
|
||||
#####################################
|
||||
# builds and sends $discover_count
|
||||
# number of DHCP DISCOVER messages
|
||||
# GLOBAL VARS: CS, FLAGS, Server_pport
|
||||
# Haddr
|
||||
#####################################
|
||||
sub send_discovers {
|
||||
local($discover_count) = @_;
|
||||
local($xid, $msg, $hostname, $hnlen, $tmp);
|
||||
|
||||
$xid = $Haddr; # initialize incremental variables
|
||||
|
||||
# build and send DISCOVER messages
|
||||
while ($discover_count-- > 0) {
|
||||
|
||||
$msg = sprintf("0fffffff%04x", $Haddr);
|
||||
$Offers{$msg} = $TRUE; # this DISCOVER msg has an outstanding
|
||||
# OFFER msg
|
||||
$Acks{$msg} = $TRUE; # this DISCOVER msg has an outstanding
|
||||
# ACK msg
|
||||
|
||||
# op, htype, hlen, hops
|
||||
$msg = pack("H2" x 4, "01", "01", "06", "00");
|
||||
# xid, secs, flags
|
||||
$msg .= pack("H4 n H8", "eeee", $xid++, 0);
|
||||
# ciaddr, yiaddr, siaddr, giaddr
|
||||
if ($Relay) {
|
||||
$msg .= pack("H8 H8 H8 C4", 0, 0, 0, unpack("C4", $Client_ipaddr[0]));
|
||||
}
|
||||
else { $msg .= pack("H8 H8 H8 H8", 0, 0, 0, 0); }
|
||||
|
||||
# chaddr
|
||||
$msg .= pack("H8 n H20", "0fffffff", $Haddr, 0);
|
||||
$msg .= pack("H384", "0"); # sname, file
|
||||
$msg .= pack("H8", "63825363"); # magic cookie
|
||||
$msg .= pack("H6", "350101"); # message type DISCOVER
|
||||
# client ID = chaddr
|
||||
$msg .= pack("H4 H8 n", "3d06", "0fffffff", $Haddr);
|
||||
|
||||
### create unique hostname ###
|
||||
$tmp = sprintf("dhcp-client-%05d", $Haddr++);
|
||||
$hostname = "";
|
||||
while (length($tmp) > 0) { # convert string to hex
|
||||
$hostname .= sprintf("%02x", ord($tmp));
|
||||
$tmp =~ s/^.//;
|
||||
}
|
||||
$hnlen = length($hostname); # hostname length
|
||||
$msg .= pack("H2 C H$hnlen", "0c", $hnlen/2, "$hostname");
|
||||
|
||||
$msg .= pack("H2", "ff"); # end of options
|
||||
# send msg
|
||||
send(CS, $msg, $FLAGS, $Server_pport);
|
||||
}
|
||||
}
|
||||
#####################################
|
||||
# resends DHCP DISCOVER messages
|
||||
# for each HW addr in %Offers
|
||||
# GLOBAL VARS: CS, FLAGS, Server_pport
|
||||
# Haddr, Retry, Delay
|
||||
# RETURNS: number of DISCOVERs sent
|
||||
#####################################
|
||||
sub rediscover {
|
||||
local($xid, $msg, $cnt, $hostname, $hnlen, $tmp);
|
||||
|
||||
$cnt = 0;
|
||||
$Retry++;
|
||||
# build and send DISCOVER messages
|
||||
foreach $Haddr (keys %Offers) {
|
||||
$xid = $Haddr;
|
||||
$xid =~ s/^0fffffff//; # behead MAC addr prefix
|
||||
|
||||
# op, htype, hlen, hops
|
||||
$msg = pack("H2" x 4, "01", "01", "06", "00");
|
||||
# xid, secs, flags
|
||||
$msg .= pack("H4 n H8", "eeee", $xid, 0);
|
||||
# ciaddr, yiaddr, siaddr, giaddr
|
||||
if ($Relay) {
|
||||
$msg .= pack("H8 H8 H8 C4", 0, 0, 0, unpack("C4", $Client_ipaddr[0]));
|
||||
}
|
||||
else { $msg .= pack("H8 H8 H8 H8", 0, 0, 0, 0); }
|
||||
|
||||
# chaddr
|
||||
$msg .= pack("H12 H20", $Haddr, 0);
|
||||
$msg .= pack("H384", "0"); # sname, file
|
||||
$msg .= pack("H8", "63825363"); # magic cookie
|
||||
$msg .= pack("H6", "350101"); # message type DISCOVER
|
||||
# client ID = chaddr
|
||||
$msg .= pack("H4 H12", "3d06", $Haddr);
|
||||
|
||||
### create unique hostname ###
|
||||
$tmp = sprintf("dhcp-client-%05d", $xid);
|
||||
$hostname = "";
|
||||
while (length($tmp) > 0) { # convert string to hex
|
||||
$hostname .= sprintf("%02x", ord($tmp));
|
||||
$tmp =~ s/^.//;
|
||||
}
|
||||
$hnlen = length($hostname); # hostname length
|
||||
$msg .= pack("H2 C H$hnlen", "0c", $hnlen/2, "$hostname");
|
||||
|
||||
$msg .= pack("H2", "ff"); # end of options
|
||||
|
||||
# send msg
|
||||
send(CS, $msg, $FLAGS, $Server_pport);
|
||||
$cnt++; # incr count of msgs sent
|
||||
}
|
||||
|
||||
if ($Delay > 0) { sleep($Delay); } # give server a chance to respond
|
||||
return($cnt);
|
||||
}
|
||||
###################################
|
||||
# builds and sends a single DHCP
|
||||
# REQUEST message (if the message
|
||||
# from the server is an OFFER not
|
||||
# an ACK)
|
||||
# GLOBAL VARS: CS and almost every
|
||||
# other "local" var used herein
|
||||
# RETURNS: DHCP msg type
|
||||
###################################
|
||||
sub send_request {
|
||||
local($datagram) = @_;
|
||||
local($server_id, $msg_type, $tmp_chaddr,
|
||||
$client_id, $tmp, $hostname, $hnlen);
|
||||
|
||||
$msg_type = 0; # init local vars
|
||||
$server_id = "";
|
||||
|
||||
$DHCP_STRUCT = "H2 H2 H2 H2 H8 H4 H4 H8 H8 H8 H8 H32 H384 H8 H*";
|
||||
($op, $htype, $hlen, $hops, $xid, $secs, $flags, $ciaddr, $yiaddr, $siaddr, $giaddr, $chaddr, $sname_file, $cookie, $options) = unpack($DHCP_STRUCT, $datagram);
|
||||
|
||||
$tmp_opt = $options;
|
||||
$tmp_chaddr = substr($chaddr, 0, 12); # trunc trailing zeros
|
||||
|
||||
# determine whether this is an ACK
|
||||
# or OFFER by searching through
|
||||
# options
|
||||
while (length($tmp_opt) > 3) {
|
||||
# ASSUMES no pad options!
|
||||
$option = substr($tmp_opt, 0, 2); # extract option
|
||||
$length = substr($tmp_opt, 2, 2); # extract length
|
||||
# extract value
|
||||
$value = substr($tmp_opt, 4, 2 * hex($length));
|
||||
# behead leading option
|
||||
$tmp_opt = substr($tmp_opt, 4 + 2 * hex($length));
|
||||
|
||||
if ($option eq "35") { # if this is DHCP_Msg_Type option
|
||||
$msg_type = hex($value);
|
||||
if ($msg_type == $ACK_MSG) { # if this is an ACK
|
||||
|
||||
# if I haven't yet seen this addr's ACK
|
||||
if (defined($Acks{$tmp_chaddr})) {
|
||||
delete($Acks{$tmp_chaddr}); # remove addr from ACK list
|
||||
$Ack_cnt++; # increment number of ACKs recv'd
|
||||
}
|
||||
return($msg_type); # stop processing
|
||||
}
|
||||
|
||||
if ($msg_type != $OFFER_MSG) { # if this is NOT an OFFER
|
||||
return($msg_type); # then stop processing
|
||||
}
|
||||
}
|
||||
|
||||
if ($option eq "36") { # if this is Server_ID option
|
||||
$server_id = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($msg_type != $OFFER_MSG) { # there was no DHCP_Msg_Type option
|
||||
return($msg_type); # so stop processing
|
||||
}
|
||||
# this addr no longer has an
|
||||
# outstanding OFFER
|
||||
if (defined($Offers{$tmp_chaddr})) {
|
||||
delete($Offers{$tmp_chaddr}); # remove addr from list
|
||||
$Offer_cnt++; # increment number of OFFERs recv'd
|
||||
}
|
||||
else { return($msg_type); }
|
||||
|
||||
$rqst_msg = "350103"; # build REQUEST message type
|
||||
$addr_rqst = "3204$yiaddr"; # build address request
|
||||
if ($server_id) {
|
||||
$srvr_id = "3604$server_id"; # server identifier
|
||||
}
|
||||
else { $srvr_id = "3604$siaddr"; }
|
||||
|
||||
$client_id = "3d06$tmp_chaddr"; # client identifier
|
||||
|
||||
### create unique hostname ###
|
||||
$tmp_chaddr =~ s/^0fffffff//; # behead prefix
|
||||
$tmp = sprintf("dhcp-client-%05d", hex($tmp_chaddr));
|
||||
$hostname = "";
|
||||
while (length($tmp) > 0) { # convert string to hex
|
||||
$hostname .= sprintf("%02x", ord($tmp));
|
||||
$tmp =~ s/^.//;
|
||||
}
|
||||
$hnlen = length($hostname); # hostname length
|
||||
$hostname = sprintf("0c%02x$hostname", $hnlen/2);
|
||||
|
||||
$end_opt = "ff"; # end of options
|
||||
|
||||
$datagram = pack($DHCP_STRUCT, "01", $htype, $hlen, $hops, $xid, $secs, $flags, $ciaddr, "00000000", "00000000", $giaddr, $chaddr, $sname_file, $cookie, "$rqst_msg$addr_rqst$srvr_id$client_id$hostname$end_opt");
|
||||
|
||||
# send REQUEST msg
|
||||
send(CS, $datagram, $FLAGS, $Server_pport);
|
||||
|
||||
return($msg_type);
|
||||
}
|
||||
#########################
|
||||
# prints program usage
|
||||
#########################
|
||||
sub usage {
|
||||
print <<END_USAGE;
|
||||
|
||||
Usage: $0 <flag> <value>
|
||||
|
||||
\tFlags\tValues
|
||||
\t-a\tstarting hardware Address (default: 1)
|
||||
\t-d\tnumber of Discover messages to send (default: 1)
|
||||
\t-h, -?\tshow Help
|
||||
\t-p\tshow Progress (number of ACKs received)
|
||||
\t-r\tact like a Relay agent
|
||||
\t-R\tsuppress sending REQUEST messages
|
||||
\t-s\tServer hostname or IP address (default: broadcast)
|
||||
\t-w\tWait time (in seconds) between retries (default: 0)
|
||||
|
||||
END_USAGE
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
#################
|
||||
### MAIN CODE ###
|
||||
#################
|
||||
|
||||
$| = 1; # flush writes
|
||||
|
||||
# ensure we're root so we can
|
||||
# bind to priviledged sockets
|
||||
chomp($USER = `whoami`);
|
||||
if ($USER ne "root") {
|
||||
print "\n\t*** You must be root to run this program. ***\n";
|
||||
&usage;
|
||||
}
|
||||
|
||||
# process arguments
|
||||
while($#ARGV >= 0) {
|
||||
ARG_SWITCH: {
|
||||
if ($ARGV[0] =~ /^(-h|-\?)$/) { &usage; }
|
||||
|
||||
# show progress
|
||||
if ($ARGV[0] =~ /^-p$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Progress = $TRUE;
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# don't send request messages
|
||||
if ($ARGV[0] =~ /^-R$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Suppress_request = $TRUE;
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# act as a relay agent
|
||||
if ($ARGV[0] =~ /^-r$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Relay = $TRUE;
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# user specified server
|
||||
if ($ARGV[0] =~ /^-s$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Server_hostname = $ARGV[0];
|
||||
shift(@ARGV); # discard server hostname
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# user specified DISCOVER count
|
||||
if ($ARGV[0] =~ /^-d$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Discover_count = $ARGV[0];
|
||||
if ($Discover_count < 1 || $Discover_count > $DISC_MAX) {
|
||||
print "Discover count must be between 1 and $DISC_MAX.\n";
|
||||
exit;
|
||||
}
|
||||
shift(@ARGV); # discard server hostname
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# user specified Wait time
|
||||
if ($ARGV[0] =~ /^-w$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Delay = $ARGV[0];
|
||||
if ($Delay < 0 || $Delay > $DELAY_MAX) {
|
||||
print "Wait time be between 0 and $DELAY_MAX.\n";
|
||||
exit;
|
||||
}
|
||||
shift(@ARGV); # discard Wait time
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
# user specified starting HW addr
|
||||
if ($ARGV[0] =~ /^-a$/) {
|
||||
shift(@ARGV); # discard flag
|
||||
$Haddr = $ARGV[0];
|
||||
if ($Haddr < 1 || $Haddr > $DISC_MAX) {
|
||||
print "Starting hardware address must be between 1 and $DISC_MAX.\n";
|
||||
exit;
|
||||
}
|
||||
shift(@ARGV); # discard server hostname
|
||||
last ARG_SWITCH;
|
||||
}
|
||||
print "Unknown flag '$ARGV[0]'.\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
# create socket capable of broadcasts
|
||||
&setup_socket($Server_hostname);
|
||||
|
||||
# get the start user, system, and...
|
||||
($Start_times[0], $Start_times[1], $junk, $junk) = times;
|
||||
$Start_times[2] = time; # ...absolute times
|
||||
|
||||
# blast out all the DISCOVER msgs
|
||||
print "Sending $Discover_count DISCOVER messages...\n";
|
||||
&send_discovers($Discover_count);
|
||||
|
||||
if ($Delay > 0) { sleep($Delay); } # give server a chance to respond
|
||||
|
||||
if ($Suppress_request) { exit; } # should I process the OFFER msgs?
|
||||
|
||||
# yes
|
||||
print "Waiting for $Discover_count ACKs...\n";
|
||||
while ($Ack_cnt < $Discover_count) {
|
||||
|
||||
# if I'm supposed to report progress
|
||||
# then do so
|
||||
if ($Progress) {
|
||||
if (($Ack_cnt % 10) == 0 && $Ack_cnt > $Last_ack_cnt) {
|
||||
print "$Ack_cnt ACKs...\n";
|
||||
$Last_ack_cnt = $Ack_cnt;
|
||||
}
|
||||
}
|
||||
# receive the OFFER/ACK msg
|
||||
if ($Relay) {
|
||||
$Rc = recv(SS, $Datagram, $MAX_LEN, $FLAGS);
|
||||
}
|
||||
else { $Rc = recv(CS, $Datagram, $MAX_LEN, $FLAGS); }
|
||||
|
||||
if (! defined($Rc)) { # if no more incoming messages
|
||||
# to process
|
||||
if ($Offer_cnt < $Discover_count) {
|
||||
&rediscover;
|
||||
}
|
||||
else { # we've received all the OFFERs
|
||||
|
||||
if ($Ack_cnt < $Discover_count) { # if we're missing some ACKs
|
||||
%Offers = %Acks; # then reDISCOVER (rather than
|
||||
# reREQUEST as advised in RFC2131;
|
||||
# this choice is for the sake of
|
||||
# simplicity in this program)
|
||||
$Offer_cnt = $Ack_cnt;
|
||||
&rediscover;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { # I have a reply to process
|
||||
&send_request($Datagram); # send the REQUEST msg
|
||||
}
|
||||
}
|
||||
### print statistics ###
|
||||
|
||||
print "Received $Ack_cnt Acks.\n";
|
||||
|
||||
# get the ending user, system, and...
|
||||
($End_times[0], $End_times[1], $junk, $junk) = times;
|
||||
$End_times[2] = time; # ...absolute times
|
||||
|
||||
printf("\nTimes: %.2f user, %.2f system, %d elapsed\n",
|
||||
$End_times[0] - $Start_times[0],
|
||||
$End_times[1] - $Start_times[1],
|
||||
$End_times[2] - $Start_times[2]);
|
||||
|
||||
print "Number of reDISCOVERies: $Retry\n";
|
||||
|
||||
close(CS); # close client socket
|
||||
|
||||
if ($Relay) { close(SS); } # close server socket
|
Loading…
Add table
Add a link
Reference in a new issue