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 <experimental/any>
37 #include <sstream>
38 #include <string>
39 #include <tuple>
40 #include <vector>
41 
42 namespace any_ns = std::experimental;
43 
44 namespace phosphor
45 {
46 namespace network
47 {
48 namespace snmp
49 {
50 
51 using OID = std::array<oid, MAX_OID_LEN>;
52 using OID_LEN = size_t;
53 using Type = u_char;
54 
55 using Value = std::variant<uint32_t, uint64_t, int32_t, std::string>;
56 // Generic snmp trap ID
57 oid SNMPTrapOID[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};
58 oid sysuptimeOID[] = {1, 3, 6, 1, 2, 1, 1, 3, 0};
59 
60 using Object = std::tuple<OID, OID_LEN, Type, Value>;
61 
62 /** @brief Get the ASN object type from the given templatized type.
63  *         Specialize this template for handling a specific type.
64  *  @tparam T - type of object from ASN type would be decided.
65  *  @returns the ASN object type.
66  */
67 template <typename T>
68 u_char getASNType() = delete;
69 
70 template <>
71 u_char getASNType<uint32_t>()
72 {
73     return ASN_UNSIGNED;
74 }
75 
76 template <>
77 u_char getASNType<uint64_t>()
78 {
79     return ASN_OPAQUE_U64;
80 }
81 
82 template <>
83 u_char getASNType<int32_t>()
84 {
85     return ASN_INTEGER;
86 }
87 
88 template <>
89 u_char getASNType<std::string>()
90 {
91     return ASN_OCTET_STR;
92 }
93 
94 /** @class Notification
95  *  @brief Notification interface.
96  *
97  *  This class implements the sendTrap function which
98  *  send the list of objects defined by the specific notification
99  *  to the configured SNMP manager.
100  */
101 
102 class Notification
103 {
104 
105   public:
106     Notification() = default;
107     Notification(const Notification&) = delete;
108     Notification(Notification&&) = default;
109     Notification& operator=(const Notification&) = delete;
110     Notification& operator=(Notification&&) = default;
111     virtual ~Notification() = default;
112 
113     /** @brief Send the snmp trap to the configured
114      *          manager.
115      */
116     void sendTrap();
117 
118   protected:
119     /** @brief Add the variable in the snmp pdu object.
120      *  @param[in] pdu - SNMP pdu object.
121      *  @param[in] objID -  SNMP object identifier.
122      *  @param[in] objIDLen - Object identifier length.
123      *  @param[in] type - ASN type of object.
124      *  @param[in] val - Value of the object.
125      *  @returns true on success otherwise false.
126      */
127     bool addPDUVar(netsnmp_pdu& pdu, const OID& objID, size_t objIDLen,
128                    u_char type, Value val);
129 
130     /** @brief get the SNMP notification type in the mib
131      *         defined format.
132      *         This is pure virtual function all the subclasses
133      *         need to provide its own defined type.
134      *  @returns the notification type string.
135      */
136     virtual std::pair<OID, OID_LEN> getTrapOID() = 0;
137 
138     /** @brief get all the objects meta data defined under
139      *         this notification.
140      */
141     virtual std::vector<Object> getFieldOIDList() = 0;
142 };
143 
144 class TestErrorNotification;
145 
146 /** @class ErrorNotification
147  *  @brief subclass of Notification
148  *
149  *  A Error Notification represents the objects needed by the
150  *  Error Object.
151  */
152 class OBMCErrorNotification : public Notification
153 {
154 
155   private:
156     uint32_t OBMCErrorID;
157     uint64_t OBMCErrorTimestamp;
158     int32_t OBMCErrorSeverity;
159     std::string OBMCErrorMessage;
160 
161   public:
162     OBMCErrorNotification() = default;
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),
178         OBMCErrorTimestamp(ts), OBMCErrorSeverity(sev), 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 
194         OID_LEN idLen = 11;
195         OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 1};
196         auto type = getASNType<decltype(OBMCErrorID)>();
197         auto tuple =
198             std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type, OBMCErrorID);
199 
200         objectList.emplace_back(std::move(tuple));
201 
202         id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 2};
203         type = getASNType<decltype(OBMCErrorTimestamp)>();
204         tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
205                                                       OBMCErrorTimestamp);
206 
207         objectList.emplace_back(std::move(tuple));
208 
209         id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 3};
210         type = getASNType<decltype(OBMCErrorSeverity)>();
211 
212         tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
213                                                       OBMCErrorSeverity);
214 
215         objectList.emplace_back(std::move(tuple));
216 
217         id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 4};
218         type = getASNType<decltype(OBMCErrorMessage)>();
219 
220         tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
221                                                       OBMCErrorMessage);
222 
223         objectList.emplace_back(std::move(tuple));
224 
225         return objectList;
226     }
227 
228     friend class TestErrorNotification;
229 };
230 
231 } // namespace snmp
232 } // namespace network
233 } // namespace phosphor
234