|
# 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
|