1 /**
2  * @brief SNMP Error Notification class.
3  *
4  * This file is part of phosphor-snmp project.
5  *
6  * Copyright (c) 2018 IBM Corporation
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Note: In near future this file will be autogenerated by the custom parser.
21  *
22  */
23 
24 #pragma once
25 
26 // net-snmp requires a very specific header include order.
27 // disable clang-format around this block
28 // clang-format off
29 #include <net-snmp/net-snmp-config.h>
30 #include <net-snmp/net-snmp-includes.h>
31 #include <net-snmp/agent/net-snmp-agent-includes.h>
32 // clang-format on
33 
34 #include <sdbusplus/server.hpp>
35 
36 #include <sstream>
37 #include <string>
38 #include <vector>
39 
40 namespace phosphor
41 {
42 namespace network
43 {
44 namespace snmp
45 {
46 
47 using OID = std::array<oid, MAX_OID_LEN>;
48 using OID_LEN = size_t;
49 using Type = u_char;
50 
51 using Value = std::variant<uint32_t, uint64_t, int32_t, std::string>;
52 // Generic snmp trap ID
53 oid SNMPTrapOID[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};
54 oid sysuptimeOID[] = {1, 3, 6, 1, 2, 1, 1, 3, 0};
55 
56 struct Object
57 {
58     OID oid;
59     OID_LEN oid_len;
60     Type type;
61     Value value;
62 };
63 
64 /** @brief Get the ASN object type from the given templatized type.
65  *         Specialize this template for handling a specific type.
66  *  @tparam T - type of object from ASN type would be decided.
67  *  @returns the ASN object type.
68  */
69 template <typename T>
70 u_char getASNType() = delete;
71 
72 template <>
73 u_char getASNType<uint32_t>()
74 {
75     return ASN_UNSIGNED;
76 }
77 
78 template <>
79 u_char getASNType<uint64_t>()
80 {
81     return ASN_OPAQUE_U64;
82 }
83 
84 template <>
85 u_char getASNType<int32_t>()
86 {
87     return ASN_INTEGER;
88 }
89 
90 template <>
91 u_char getASNType<std::string>()
92 {
93     return ASN_OCTET_STR;
94 }
95 
96 /** @class Notification
97  *  @brief Notification interface.
98  *
99  *  This class implements the sendTrap function which
100  *  send the list of objects defined by the specific notification
101  *  to the configured SNMP manager.
102  */
103 
104 class Notification
105 {
106   public:
107     Notification() = default;
108     Notification(const Notification&) = delete;
109     Notification(Notification&&) = default;
110     Notification& operator=(const Notification&) = delete;
111     Notification& operator=(Notification&&) = default;
112     virtual ~Notification() = default;
113 
114     /** @brief Send the snmp trap to the configured
115      *          manager.
116      */
117     void sendTrap();
118 
119   protected:
120     /** @brief Add the variable in the snmp pdu object.
121      *  @param[in] pdu - SNMP pdu object.
122      *  @param[in] objID -  SNMP object identifier.
123      *  @param[in] objIDLen - Object identifier length.
124      *  @param[in] type - ASN type of object.
125      *  @param[in] val - Value of the object.
126      *  @returns true on success otherwise false.
127      */
128     bool addPDUVar(netsnmp_pdu& pdu, const OID& objID, size_t objIDLen,
129                    u_char type, Value val);
130 
131     /** @brief get the SNMP notification type in the mib
132      *         defined format.
133      *         This is pure virtual function all the subclasses
134      *         need to provide its own defined type.
135      *  @returns the notification type string.
136      */
137     virtual std::pair<OID, OID_LEN> getTrapOID() = 0;
138 
139     /** @brief get all the objects meta data defined under
140      *         this notification.
141      */
142     virtual std::vector<Object> getFieldOIDList() = 0;
143 };
144 
145 class TestErrorNotification;
146 
147 /** @class ErrorNotification
148  *  @brief subclass of Notification
149  *
150  *  A Error Notification represents the objects needed by the
151  *  Error Object.
152  */
153 class OBMCErrorNotification : public Notification
154 {
155   private:
156     uint32_t OBMCErrorID = 0;
157     uint64_t OBMCErrorTimestamp = 0;
158     int32_t OBMCErrorSeverity = 0;
159     std::string OBMCErrorMessage;
160 
161   public:
162     OBMCErrorNotification() = delete;
163     OBMCErrorNotification(const OBMCErrorNotification&) = delete;
164     OBMCErrorNotification(OBMCErrorNotification&&) = default;
165     OBMCErrorNotification& operator=(const OBMCErrorNotification&) = delete;
166     OBMCErrorNotification& operator=(OBMCErrorNotification&&) = default;
167     ~OBMCErrorNotification() = default;
168 
169     /** @brief Constructor
170      *  @param[in] id - The error entry id.
171      *  @param[in] ts - The commit timestamp.
172      *  @param[in] sev - The severity of the error.
173      *  @param[in] msg - The message of the error.
174      */
175     OBMCErrorNotification(uint32_t id, uint64_t ts, int32_t sev,
176                           std::string msg) :
177         OBMCErrorID(id), OBMCErrorTimestamp(ts), OBMCErrorSeverity(sev),
178         OBMCErrorMessage(msg)
179     {}
180 
181   protected:
182     std::pair<OID, OID_LEN> getTrapOID() override
183     {
184         // notification sub types
185         OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 0, 1};
186         OID_LEN idLen = 11;
187         return std::make_pair<OID, OID_LEN>(std::move(id), std::move(idLen));
188     }
189 
190     std::vector<Object> getFieldOIDList() override
191     {
192         std::vector<Object> objectList;
193         objectList.reserve(4);
194         {
195             OID_LEN idLen = 11;
196             OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 1};
197             u_char type = getASNType<decltype(OBMCErrorID)>();
198 
199             objectList.emplace_back(id, idLen, type, OBMCErrorID);
200         }
201         {
202             OID_LEN idLen = 11;
203             OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 2};
204             u_char type = getASNType<decltype(OBMCErrorTimestamp)>();
205 
206             objectList.emplace_back(id, idLen, type, OBMCErrorTimestamp);
207         }
208         {
209             OID_LEN idLen = 11;
210             OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 3};
211             u_char type = getASNType<decltype(OBMCErrorSeverity)>();
212 
213             objectList.emplace_back(id, idLen, type, OBMCErrorSeverity);
214         }
215         {
216             OID_LEN idLen = 11;
217             OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 4};
218             u_char type = getASNType<decltype(OBMCErrorMessage)>();
219 
220             objectList.emplace_back(id, idLen, type, OBMCErrorMessage);
221         }
222         return objectList;
223     }
224 
225     friend class TestErrorNotification;
226 };
227 
228 } // namespace snmp
229 } // namespace network
230 } // namespace phosphor
231