snmp_agent_trap.c
Go to the documentation of this file.
1 /**
2  * @file snmp_agent_trap.c
3  * @brief SNMP trap notifications
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL SNMP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "snmp/snmp_agent.h"
35 #include "snmp/snmp_agent_misc.h"
36 #include "snmp/snmp_agent_trap.h"
37 #include "mibs/mib2_module.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (SNMP_AGENT_SUPPORT == ENABLED && SNMP_AGENT_TRAP_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Format SNMP Trap message
46  * @param[in] context Pointer to the SNMP agent context
47  * @param[in] version SNMP version identifier
48  * @param[in] userName User name or community name
49  * @param[in] genericTrapType Generic trap type
50  * @param[in] specificTrapCode Specific code
51  * @param[in] objectList List of object names
52  * @param[in] objectListSize Number of entries in the list
53  * @return Error code
54  **/
55 
57  const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode,
58  const SnmpTrapObject *objectList, uint_t objectListSize)
59 {
60  error_t error;
61 
62 #if (SNMP_V1_SUPPORT == ENABLED)
63  //SNMPv1 version?
64  if(version == SNMP_VERSION_1)
65  {
66  //Format Trap-PDU
67  error = snmpFormatTrapPdu(context, version, userName,
68  genericTrapType, specificTrapCode, objectList, objectListSize);
69  //Any error to report?
70  if(error)
71  return error;
72 
73  //Format SMNP message header
74  error = snmpWriteMessageHeader(&context->response);
75  //Any error to report?
76  if(error)
77  return error;
78  }
79  else
80 #endif
81 #if (SNMP_V2C_SUPPORT == ENABLED)
82  //SNMPv2c version?
84  {
85  //Format SNMPv2-Trap-PDU
86  error = snmpFormatTrapPdu(context, version, userName,
87  genericTrapType, specificTrapCode, objectList, objectListSize);
88  //Any error to report?
89  if(error)
90  return error;
91 
92  //Format SMNP message header
93  error = snmpWriteMessageHeader(&context->response);
94  //Any error to report?
95  if(error)
96  return error;
97  }
98  else
99 #endif
100 #if (SNMP_V3_SUPPORT == ENABLED)
101  //SNMPv3 version?
102  if(version == SNMP_VERSION_3)
103  {
104  SnmpUserEntry *user;
105 
106  //Information about the user name is extracted from the local
107  //configuration datastore
108  user = snmpFindUserEntry(context, userName, strlen(userName));
109 
110  //Invalid user name?
111  if(user == NULL || user->status != MIB_ROW_STATUS_ACTIVE)
113 
114  //Save the security profile associated with the current user
115  context->user = *user;
116 
117  //Format SNMPv2-Trap-PDU
118  error = snmpFormatTrapPdu(context, version, userName,
119  genericTrapType, specificTrapCode, objectList, objectListSize);
120  //Any error to report?
121  if(error)
122  return error;
123 
124  //Format scopedPDU
125  error = snmpWriteScopedPdu(&context->response);
126  //Any error to report?
127  if(error)
128  return error;
129 
130  //Check whether the privFlag is set
131  if(context->response.msgFlags & SNMP_MSG_FLAG_PRIV)
132  {
133  //Encrypt data
134  error = snmpEncryptData(&context->user, &context->response,
135  &context->salt);
136  //Any error to report?
137  if(error)
138  return error;
139  }
140 
141  //Format SMNP message header
142  error = snmpWriteMessageHeader(&context->response);
143  //Any error to report?
144  if(error)
145  return error;
146 
147  //Check whether the authFlag is set
148  if(context->response.msgFlags & SNMP_MSG_FLAG_AUTH)
149  {
150  //Authenticate outgoing SNMP message
151  error = snmpAuthOutgoingMessage(&context->user, &context->response);
152  //Any error to report?
153  if(error)
154  return error;
155  }
156  }
157  else
158 #endif
159  //Invalid SNMP version?
160  {
161  //Debug message
162  TRACE_WARNING(" Invalid SNMP version!\r\n");
163  //Report an error
164  return ERROR_INVALID_VERSION;
165  }
166 
167  //Successful processing
168  return NO_ERROR;
169 }
170 
171 
172 /**
173  * @brief Format Trap-PDU or SNMPv2-Trap-PDU
174  * @param[in] context Pointer to the SNMP agent context
175  * @param[in] version SNMP version identifier
176  * @param[in] userName User name or community name
177  * @param[in] genericTrapType Generic trap type
178  * @param[in] specificTrapCode Specific code
179  * @param[in] objectList List of object names
180  * @param[in] objectListSize Number of entries in the list
181  * @return Error code
182  **/
183 
185  const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode,
186  const SnmpTrapObject *objectList, uint_t objectListSize)
187 {
188  error_t error;
190 
191  //Point to the SNMP message
192  message = &context->response;
193  //Initialize SNMP message
195 
196  //SNMP version identifier
197  message->version = version;
198 
199 #if (SNMP_V1_SUPPORT == ENABLED)
200  //SNMPv1 version?
201  if(version == SNMP_VERSION_1)
202  {
203 #if (IPV4_SUPPORT == ENABLED)
204  NetInterface *interface;
205 
206  //Point to the underlying network interface
207  interface = context->settings.interface;
208 #endif
209 
210  //Community name
211  message->community = userName;
212  message->communityLen = strlen(userName);
213 
214  //Prepare to send a Trap-PDU
215  message->pduType = SNMP_PDU_TRAP;
216  //Type of object generating trap
217  message->enterpriseOid = context->enterpriseOid;
218  message->enterpriseOidLen = context->enterpriseOidLen;
219 
220 #if (IPV4_SUPPORT == ENABLED)
221  //Address of object generating trap
222  if(interface != NULL)
223  message->agentAddr = interface->ipv4Context.addr;
224 #endif
225 
226  //Generic trap type
227  message->genericTrapType = genericTrapType;
228  //Specific trap code
229  message->specificTrapCode = specificTrapCode;
230  //Timestamp
231  message->timestamp = osGetSystemTime() / 10;
232  }
233  else
234 #endif
235 #if (SNMP_V2C_SUPPORT == ENABLED)
236  //SNMPv2c version?
237  if(version == SNMP_VERSION_2C)
238  {
239  //Community name
240  message->community = userName;
241  message->communityLen = strlen(userName);
242 
243  //Prepare to send a SNMPv2-Trap-PDU
244  message->pduType = SNMP_PDU_TRAP_V2;
245  }
246  else
247 #endif
248 #if (SNMP_V3_SUPPORT == ENABLED)
249  //SNMPv3 version?
250  if(version == SNMP_VERSION_3)
251  {
252  //Increment message identifier
253  message->msgId = context->msgId++;
254  //Wrap around if necessary
255  if(context->msgId < 0)
256  context->msgId = 0;
257 
258  //Maximum message size supported by the sender
259  message->msgMaxSize = SNMP_MAX_MSG_SIZE;
260 
261  //Bit fields which control processing of the message
262  if(context->user.authProtocol != SNMP_AUTH_PROTOCOL_NONE)
263  message->msgFlags |= SNMP_MSG_FLAG_AUTH;
264  if(context->user.privProtocol != SNMP_PRIV_PROTOCOL_NONE)
265  message->msgFlags |= SNMP_MSG_FLAG_PRIV;
266 
267  //Security model used by the sender
268  message->msgSecurityModel = SNMP_SECURITY_MODEL_USM;
269 
270  //Authoritative engine identifier
271  message->msgAuthEngineId = context->contextEngine;
272  message->msgAuthEngineIdLen = context->contextEngineLen;
273  //Number of times the SNMP engine has rebooted
274  message->msgAuthEngineBoots = context->engineBoots;
275  //Number of seconds since last reboot
276  message->msgAuthEngineTime = context->engineTime;
277  //User name
278  message->msgUserName = userName;
279  message->msgUserNameLen = strlen(userName);
280  //Authentication parameters
281  message->msgAuthParameters = NULL;
282  //Length of the authentication parameters
283  message->msgAuthParametersLen = snmpGetMacLength(context->user.authProtocol);
284  //Privacy parameters
285  message->msgPrivParameters = context->privParameters;
286 
287  //Length of the privacy parameters
288  if(context->user.privProtocol == SNMP_PRIV_PROTOCOL_DES)
289  message->msgPrivParametersLen = 8;
290  else if(context->user.privProtocol == SNMP_PRIV_PROTOCOL_AES)
291  message->msgPrivParametersLen = 8;
292  else
293  message->msgPrivParametersLen = 0;
294 
295  //Context engine identifier
296  message->contextEngineId = context->contextEngine;
297  message->contextEngineIdLen = context->contextEngineLen;
298  //Context name
299  message->contextName = context->contextName;
300  message->contextNameLen = strlen(context->contextName);
301 
302  //Prepare to send a SNMPv2-Trap-PDU
303  message->pduType = SNMP_PDU_TRAP_V2;
304  }
305  else
306 #endif
307  //Invalid SNMP version?
308  {
309  //Report an error
310  return ERROR_INVALID_VERSION;
311  }
312 
313  //Increment request identifier
314  message->requestId = context->requestId++;
315  //Wrap around if necessary
316  if(context->requestId < 0)
317  context->requestId = 0;
318 
319  //Make room for the message header at the beginning of the buffer
320  error = snmpComputeMessageOverhead(&context->response);
321  //Any error to report?
322  if(error)
323  return error;
324 
325  //Format the list of variable bindings
326  error = snmpWriteTrapVarBindingList(context, genericTrapType,
327  specificTrapCode, objectList, objectListSize);
328  //Any error to report?
329  if(error)
330  return error;
331 
332  //Total number of SNMP Trap PDUs which have been generated by
333  //the SNMP protocol entity
334  MIB2_INC_COUNTER32(snmpGroup.snmpOutTraps, 1);
335 
336  //Format PDU header
337  error = snmpWritePduHeader(&context->response);
338  //Return status code
339  return error;
340 }
341 
342 #endif
uint16_t version
Definition: dtls_misc.h:163
SnmpUserEntry * snmpFindUserEntry(SnmpAgentContext *context, const char_t *name, size_t length)
Search the user table for a given user name.
char char_t
Definition: compiler_port.h:41
MibRowStatus status
Status of the user.
systime_t osGetSystemTime(void)
Retrieve system time.
TCP/IP stack core.
Debugging facilities.
error_t snmpComputeMessageOverhead(SnmpMessage *message)
Compute SNMP message overhead.
uint8_t message[]
Definition: chap.h:150
error_t snmpFormatTrapPdu(SnmpAgentContext *context, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Format Trap-PDU or SNMPv2-Trap-PDU.
SNMP trap notifications.
User-based security model.
MIB-II module.
error_t snmpWriteMessageHeader(SnmpMessage *message)
Format SNMP message header.
#define MIB2_INC_COUNTER32(name, value)
Definition: mib2_module.h:154
User table entry.
SnmpVersion
SNMP version identifiers.
Definition: snmp_common.h:134
SNMP agent (Simple Network Management Protocol)
Helper functions for SNMP agent.
error_t snmpFormatTrapMessage(SnmpAgentContext *context, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Format SNMP Trap message.
error_t snmpEncryptData(const SnmpUserEntry *user, SnmpMessage *message, uint64_t *salt)
Data encryption.
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
SNMP message.
error_t snmpAuthOutgoingMessage(const SnmpUserEntry *user, SnmpMessage *message)
Authenticate outgoing SNMP message.
#define TRACE_WARNING(...)
Definition: debug.h:78
unsigned int uint_t
Definition: compiler_port.h:43
Object descriptor for trap notifications.
#define NetInterface
Definition: net.h:34
#define SNMP_MAX_MSG_SIZE
Definition: snmp_common.h:58
#define SnmpAgentContext
Definition: snmp_agent.h:34
No authentication.
error_t snmpWriteScopedPdu(SnmpMessage *message)
Format scopedPDU.
void snmpInitMessage(SnmpMessage *message)
Initialize a SNMP message.
size_t snmpGetMacLength(SnmpAuthProtocol authProtocol)
Get the length of the truncated MAC for a given authentication protocol.
error_t snmpWriteTrapVarBindingList(SnmpAgentContext *context, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Format the variable binding list for Trap-PDU or SNMPv2-Trap-PDU.
error_t snmpWritePduHeader(SnmpMessage *message)
Format PDU header.