# File radius/packet.rb, line 106 def unpack(data) p_hdr = "CCna16a*" rcodes = { 1 => 'Access-Request', 2 => 'Access-Accept', 3 => 'Access-Reject', 4 => 'Accounting-Request', 5 => 'Accounting-Response', 11 => 'Access-Challenge', 12 => 'Status-Server', 13 => 'Status-Client' } @code, @identifier, len, @authenticator, attrdat = data.unpack(p_hdr) @code = rcodes[@code] unset_all while (attrdat.length > 0) length = attrdat.unpack("xC")[0].to_i tval, value = attrdat.unpack("Cxa#{length-2}") tval = tval.to_i if (tval == VSA_TYPE) # handle vendor-specific attributes vid, vtype, vlength = value.unpack("NCC") # XXX - How do we calculate the length of the VSA? It's not # defined! # XXX - 3COM seems to do things a bit differently. The 'if' # below takes care of that. This is based on the # Net::Radius code. if vid == 429 # 3COM packet vid, vtype = value.unpack("NN") vvalue = value.unpack("xxxxxxxxa#{length - 10}")[0] else vvalue = value.unpack("xxxxxxa#{vlength - 2}")[0] end type = @dict.vsattr_numtype(vid, vtype) if type == nil raise "Garbled vendor-specific attribute #{vid}/#{vtype}" end val = case type when 'string' then vvalue when 'integer' (@dict.vsaval_has_name(vid, vtype)) ? @dict.vsaval_name(vid, vtype, vvalue.unpack("N")[0]) : vvalue.unpack("N")[0] when 'ipaddr' then inet_ntoa(vvalue) when 'time' then vvalue.unpack("N")[0] when 'date' then vvalue.unpack("N")[0] else raise "Unknown VSattribute type found: #{vtype}" end set_vsattr(vid, @dict.vsattr_name(vid, vtype), val) else type = @dict.attr_numtype(tval) raise "Garbled attribute #{tval}" if (type == nil) val = case type when 'string' then value when 'integer' @dict.val_has_name(tval) ? @dict.val_name(tval, value.unpack("N")[0]) : value.unpack("N")[0] when 'ipaddr' then inet_ntoa(value.unpack("N")[0]) when 'time' then value.unpack("N")[0] when 'date' then value.unpack("N")[0] else raise "Unknown attribute type found: #{type}" end set_attr(@dict.attr_name(tval), val) end attrdat[0, length] = "" end end