master
go 72 lines 1.94 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package panos
4
5 import (
6 "encoding/xml"
7 "fmt"
8 "strings"
9 )
10
11 type panosResultResponse struct {
12 XMLName xml.Name `xml:"response"`
13 Status string `xml:"status,attr"`
14 Code string `xml:"code,attr"`
15 Message panosResponseMessage `xml:"msg"`
16 Result struct {
17 Message panosResponseMessage `xml:"msg"`
18 InnerXML string `xml:",innerxml"`
19 } `xml:"result"`
20 }
21
22 func decodePANOSResult(body []byte, context string, dst any) error {
23 innerXML, err := decodePANOSResultInner(body, context)
24 if err != nil {
25 return err
26 }
27 if strings.TrimSpace(innerXML) == "" || dst == nil {
28 return nil
29 }
30
31 wrapped := []byte("<result>" + innerXML + "</result>")
32 if err := xml.Unmarshal(wrapped, dst); err != nil {
33 return fmt.Errorf("parse %s result: %w", context, err)
34 }
35 return nil
36 }
37
38 func decodePANOSResultInner(body []byte, context string) (string, error) {
39 var resp panosResultResponse
40 if err := xml.Unmarshal(body, &resp); err != nil {
41 return "", fmt.Errorf("parse %s: %w", context, err)
42 }
43 if resp.failed() {
44 return "", panosResponseError{code: resp.Code, message: resp.errorMessage()}
45 }
46 return resp.Result.InnerXML, nil
47 }
48
49 func (r panosResultResponse) failed() bool {
50 status := strings.ToLower(strings.TrimSpace(r.Status))
51 if status == "error" || status == "failed" {
52 return true
53 }
54 code := strings.TrimSpace(r.Code)
55 // PAN-OS XML API uses 19 and 20 for successful command and operation responses.
56 if code == "" || code == "0" || code == "19" || code == "20" {
57 return false
58 }
59 return true
60 }
61
62 func (r panosResultResponse) errorMessage() string {
63 return firstNonEmpty(r.Message.String(), r.Result.Message.String(), panosResponseCodeName(r.Code))
64 }
65
66 type missingPANOSResultError struct {
67 expected string
68 }
69
70 func (e missingPANOSResultError) Error() string {
71 return fmt.Sprintf("PAN-OS XML API success response has no recognized telemetry payload; expected %s", e.expected)
72 }