Class: DHCP::Message
- Inherits:
-
Object
- Object
- DHCP::Message
- Defined in:
- lib/net/dhcp/core.rb
Overview
————————————————————– dhcp messages
Instance Attribute Summary collapse
-
#chaddr ⇒ Object
Returns the value of attribute chaddr.
-
#ciaddr ⇒ Object
Returns the value of attribute ciaddr.
-
#flags ⇒ Object
Returns the value of attribute flags.
-
#fname ⇒ Object
Returns the value of attribute fname.
-
#giaddr ⇒ Object
Returns the value of attribute giaddr.
-
#hlen ⇒ Object
Returns the value of attribute hlen.
-
#hops ⇒ Object
Returns the value of attribute hops.
-
#htype ⇒ Object
Returns the value of attribute htype.
-
#op ⇒ Object
Returns the value of attribute op.
-
#options ⇒ Object
Returns the value of attribute options.
-
#secs ⇒ Object
Returns the value of attribute secs.
-
#siaddr ⇒ Object
Returns the value of attribute siaddr.
-
#sname ⇒ Object
Returns the value of attribute sname.
-
#xid ⇒ Object
Returns the value of attribute xid.
-
#yiaddr ⇒ Object
Returns the value of attribute yiaddr.
Class Method Summary collapse
Instance Method Summary collapse
- #== ⇒ Object
- #eql?(obj) ⇒ Boolean
-
#initialize(params = {}) ⇒ Message
constructor
A new instance of Message.
- #pack ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(params = {}) ⇒ Message
Returns a new instance of Message.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/net/dhcp/core.rb', line 108 def initialize(params = {}) # message operation and options. We need at least an operation and a # MessageTypeOption to create a DHCP message!! if (([:op, :options] & params.keys).size != 2) raise ArgumentError, 'you need to specify at least values for :op and :options' end self.op = params[:op] self. = params[:options] found = false self..each do |opt| next unless opt.class == MessageTypeOption found = true end raise ArgumentError, ':options must include a MessageTypeOption' unless found #hardware type and length of the hardware address self.htype = params.fetch(:htype, $DHCP_HTYPE_ETHERNET) self.hlen = params.fetch(:hlen, $DHCP_HLEN_ETHERNET) # client sets to zero. relay agents may modify self.hops = params.fetch(:hops, 0x00) # initialize a random transaction ID self.xid = params.fetch(:xid, rand(2**32)) # seconds elapsed, flags self.secs = params.fetch(:secs, 0x0000) self.flags = params.fetch(:flags, 0x0000) # client, you, next server and relay agent addresses self.ciaddr = params.fetch(:ciaddr, 0x00000000) self.yiaddr = params.fetch(:yiaddr, 0x00000000) self.siaddr = params.fetch(:siaddr, 0x00000000) self.giaddr = params.fetch(:giaddr, 0x00000000) if (params.key?(:chaddr)) self.chaddr = params[:chaddr] raise 'chaddr field should be of 16 bytes' unless self.chaddr.size == 16 else if Gem.respond_to?(:win_platform?) && Gem.win_platform? mac_line = `getmac /fo list`.split("\n").grep(/Physical Address/).first if mac_line mac = mac_line.strip.split(":")[1].gsub("-","").strip end else ifcfg_out = `/sbin/ifconfig`.chomp matches1 = ifcfg_out.scan(/HWaddr ([a-h0-9:]+)/i).flatten # Linux matches2 = ifcfg_out.scan(/ether ([a-h0-9:]+)/i).flatten # Some Linux (EL7), BSDs mac = matches1.first || matches2.first mac = mac.gsub(/:/,"") if mac end mac = '000000000000' if mac.empty? self.chaddr = [mac].pack('H*').unpack('CCCCCC') self.chaddr += [0x00]*(16-self.chaddr.size) end if (params.key?(:sname)) sname = params[:sname] case when sname.size == 64 self.sname = sname when sname.size < 64 && sname.class == String self.sname = sname.unpack('C64').map {|x| x ? x : 0} else raise 'sname field should be of 64 bytes or a string of less' end else self.sname = [0x00]*64 end if (params.key?(:fname)) fname = params[:fname] case when fname.size == 128 self.fname = fname when fname.size < 128 && fname.class == String self.fname = fname.unpack('C128').map {|x| x ? x : 0} else raise 'fname field should be of 128 bytes or a string of less' end else self.fname = [0x00]*128 end end |
Instance Attribute Details
#chaddr ⇒ Object
Returns the value of attribute chaddr.
33 34 35 |
# File 'lib/net/dhcp/core.rb', line 33 def chaddr @chaddr end |
#ciaddr ⇒ Object
Returns the value of attribute ciaddr.
33 34 35 |
# File 'lib/net/dhcp/core.rb', line 33 def ciaddr @ciaddr end |
#flags ⇒ Object
Returns the value of attribute flags.
32 33 34 |
# File 'lib/net/dhcp/core.rb', line 32 def flags @flags end |
#fname ⇒ Object
Returns the value of attribute fname.
34 35 36 |
# File 'lib/net/dhcp/core.rb', line 34 def fname @fname end |
#giaddr ⇒ Object
Returns the value of attribute giaddr.
33 34 35 |
# File 'lib/net/dhcp/core.rb', line 33 def giaddr @giaddr end |
#hlen ⇒ Object
Returns the value of attribute hlen.
30 31 32 |
# File 'lib/net/dhcp/core.rb', line 30 def hlen @hlen end |
#hops ⇒ Object
Returns the value of attribute hops.
30 31 32 |
# File 'lib/net/dhcp/core.rb', line 30 def hops @hops end |
#htype ⇒ Object
Returns the value of attribute htype.
30 31 32 |
# File 'lib/net/dhcp/core.rb', line 30 def htype @htype end |
#op ⇒ Object
Returns the value of attribute op.
30 31 32 |
# File 'lib/net/dhcp/core.rb', line 30 def op @op end |
#options ⇒ Object
Returns the value of attribute options.
35 36 37 |
# File 'lib/net/dhcp/core.rb', line 35 def @options end |
#secs ⇒ Object
Returns the value of attribute secs.
32 33 34 |
# File 'lib/net/dhcp/core.rb', line 32 def secs @secs end |
#siaddr ⇒ Object
Returns the value of attribute siaddr.
33 34 35 |
# File 'lib/net/dhcp/core.rb', line 33 def siaddr @siaddr end |
#sname ⇒ Object
Returns the value of attribute sname.
34 35 36 |
# File 'lib/net/dhcp/core.rb', line 34 def sname @sname end |
#xid ⇒ Object
Returns the value of attribute xid.
31 32 33 |
# File 'lib/net/dhcp/core.rb', line 31 def xid @xid end |
#yiaddr ⇒ Object
Returns the value of attribute yiaddr.
33 34 35 |
# File 'lib/net/dhcp/core.rb', line 33 def yiaddr @yiaddr end |
Class Method Details
.from_udp_payload(data, opts = {}) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/net/dhcp/core.rb', line 39 def Message.from_udp_payload(data, opts={}) opts = {:debug => true}.merge(opts) values = data.unpack('C4Nn2N4C16C192NC*') params = { :op => values.shift, :htype => values.shift, :hlen => values.shift, :hops => values.shift, :xid => values.shift, :secs => values.shift, :flags => values.shift, :ciaddr => values.shift, :yiaddr => values.shift, :siaddr => values.shift, :giaddr => values.shift, :chaddr => values.slice!(0..15), :sname => values.slice!(0..63), :fname => values.slice!(0..127), } # sname and file are now used #not_used = values.slice!(0..191) 127+63 190 return nil unless ($DHCP_MAGIC == values.shift) #default message class msg_class = Message #default option class opt_class = Option params[:options] = [] next_opt = values.shift while(next_opt != $DHCP_END) p = { :type => next_opt, :len => values.shift } p[:payload] = values.slice!(0..p[:len]-1) # check what is the type of dhcp option opt_class = $DHCP_MSG_OPTIONS[p[:type]] if opt_class.nil? if opts[:debug] puts '-------------------- please further investigate!!' puts p[:type] puts '-------------------- /' end opt_class = Option end if (opt_class == MessageTypeOption) msg_class = $DHCP_MSG_CLASSES[p[:payload].first] end params[:options] << opt_class.new(p) next_opt = values.shift end if msg_class.nil? if opts[:debug] puts '-------------------- please further investigate!!' p params[:options] puts '-------------------- /' end msg_class = Message end msg_class.new(params) end |
Instance Method Details
#== ⇒ Object
37 |
# File 'lib/net/dhcp/core.rb', line 37 alias == eql? |
#eql?(obj) ⇒ Boolean
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/net/dhcp/core.rb', line 233 def eql?(obj) # objects must be of the same class return false unless (self.class == obj.class) vars1 = self.instance_variables # first make sure that the :options var is equal opt1 = self.instance_variable_get('@options') opt2 = obj.instance_variable_get('@options') return false unless opt1.eql?(opt2) vars1.delete('@options') # check all the other instance vairables vars1.each do |var| return false unless (self.instance_variable_get(var) == obj.instance_variable_get(var)) end return true end |
#pack ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/net/dhcp/core.rb', line 197 def pack() out = [ self.op, self.htype, self.hlen, self.hops, self.xid, self.secs, self.flags, self.ciaddr, self.yiaddr, self.siaddr, self.giaddr ].pack('C4Nn2N4') if self.chaddr.size >= 16 out << self.chaddr.pack('C16') else out << (self.chaddr + [0x00]*(16-self.chaddr.size)).pack('C16') end # file_name/server_name for pxe out << self.sname.pack('C64') out << self.fname.pack('C128') # sname and file # out << ([0x00]*192).pack('C192') out << [$DHCP_MAGIC].pack('N') self..each do |option| out << option.pack end out << [$DHCP_END].pack('C') # add padding up to 300 bytes if out.size < 300 out << ([$DHCP_PAD]*(300-out.size)).pack('C*') end return out end |
#to_s ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/net/dhcp/core.rb', line 256 def to_s out = "DHCP Message\r\n" out << "\tFIELDS:\r\n" out << "\t\tTransaction ID = 0x#{self.xid.to_s(16)}\r\n" out << "\t\tClient IP address = #{[self.ciaddr].pack('N').unpack('C4').join('.')}\r\n" out << "\t\tYour IP address = #{[self.yiaddr].pack('N').unpack('C4').join('.')}\r\n" out << "\t\tNext server IP address = #{[self.siaddr].pack('N').unpack('C4').join('.')}\r\n" out << "\t\tRelay agent IP address = #{[self.giaddr].pack('N').unpack('C4').join('.')}\r\n" out << "\t\tHardware address = #{self.chaddr.slice(0..(self.hlen-1)).collect do |b| b.to_s(16).upcase.rjust(2,'0') end.join(':')}\r\n" out << "\t\tServer Name = #{self.sname.pack('n*').unpack('A*')}\r\n" out << "\t\tFile Name = #{self.fname.pack('n*').unpack('A*')}\r\n" out << "\tOPT:\r\n" self..each do |opt| out << "\t\t #{opt.to_s}\r\n" end return out end |