RFC 7011 - part 3.B IPFIX Message Format +----------------------------------------------------+ | Message Header | +----------------------------------------------------+ | Set | +--------------------------------------
(mem MemCache, msg *Message)
| 149 | // +----------------------------------------------------+ |
| 150 | |
| 151 | func (d *Decoder) decodeSet(mem MemCache, msg *Message) error { |
| 152 | startCount := d.reader.ReadCount() |
| 153 | |
| 154 | setHeader := new(SetHeader) |
| 155 | if err := setHeader.unmarshal(d.reader); err != nil { |
| 156 | return err |
| 157 | } |
| 158 | if setHeader.Length < 4 { |
| 159 | return io.ErrUnexpectedEOF |
| 160 | } |
| 161 | |
| 162 | var tr TemplateRecord |
| 163 | var err error |
| 164 | // This check is somewhat redundant with the switch-clause below, but the retrieve() operation should not be executed inside the loop. |
| 165 | if setHeader.SetID > 255 { |
| 166 | var ok bool |
| 167 | if tr, ok = mem.retrieve(setHeader.SetID, d.raddr); !ok { |
| 168 | select { |
| 169 | case rpcChan <- RPCRequest{ |
| 170 | ID: setHeader.SetID, |
| 171 | IP: d.raddr, |
| 172 | }: |
| 173 | default: |
| 174 | } |
| 175 | err = nonfatalError{fmt.Errorf("%s unknown ipfix template id# %d", |
| 176 | d.raddr.String(), |
| 177 | setHeader.SetID, |
| 178 | )} |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | // the next set should be greater than 4 bytes otherwise that's padding |
| 183 | for err == nil && setHeader.Length > uint16(d.reader.ReadCount()-startCount) && d.reader.Len() > 4 && setHeader.Length-uint16(d.reader.ReadCount()-startCount) > 4 { |
| 184 | if setID := setHeader.SetID; setID == 2 || setID == 3 { |
| 185 | // Template record or template option record |
| 186 | |
| 187 | // Check if only padding is left in this set. A template id of zero indicates padding bytes, which MUST be zero. |
| 188 | if templateID, err := d.reader.PeekUint16(); err == nil && templateID == 0 { |
| 189 | break |
| 190 | } |
| 191 | |
| 192 | tr := TemplateRecord{} |
| 193 | if setID == 2 { |
| 194 | err = tr.unmarshal(d.reader) |
| 195 | } else { |
| 196 | err = tr.unmarshalOpts(d.reader) |
| 197 | } |
| 198 | if err == nil { |
| 199 | mem.insert(tr.TemplateID, d.raddr, tr) |
| 200 | } |
| 201 | } else if setID >= 4 && setID <= 255 { |
| 202 | // Reserved set, do not read any records |
| 203 | break |
| 204 | } else if setID == 0 { |
| 205 | // Invalid set |
| 206 | return fmt.Errorf("failed to decodeSet / invalid setID") |
| 207 | } else { |
| 208 | // Data set |
no test coverage detected