1 /** 2 * @file 3 * Management Information Base II (RFC1213) SYSTEM objects and functions. 4 */ 5 6 /* 7 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 * 32 * Author: Dirk Ziegelmeier <dziegel@gmx.de> 33 * Christiaan Simons <christiaan.simons@axon.tv> 34 */ 35 36 #include "lwip/snmp.h" 37 #include "lwip/apps/snmp.h" 38 #include "lwip/apps/snmp_core.h" 39 #include "lwip/apps/snmp_mib2.h" 40 #include "lwip/apps/snmp_table.h" 41 #include "lwip/apps/snmp_scalar.h" 42 #include "lwip/sys.h" 43 44 #include <string.h> 45 46 #if LWIP_SNMP && SNMP_LWIP_MIB2 47 48 #if SNMP_USE_NETCONN 49 #define SYNC_NODE_NAME(node_name) node_name ## _synced 50 #define CREATE_LWIP_SYNC_NODE(oid, node_name) \ 51 static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); 52 #else 53 #define SYNC_NODE_NAME(node_name) node_name 54 #define CREATE_LWIP_SYNC_NODE(oid, node_name) 55 #endif 56 57 /* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ 58 59 /** mib-2.system.sysDescr */ 60 static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; 61 static const u8_t* sysdescr = sysdescr_default; 62 static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ 63 64 /** mib-2.system.sysContact */ 65 static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; 66 static const u8_t* syscontact = syscontact_default; 67 static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ 68 static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ 69 static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ 70 static u16_t syscontact_bufsize = 0; /* 0=not writable */ 71 72 /** mib-2.system.sysName */ 73 static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; 74 static const u8_t* sysname = sysname_default; 75 static const u16_t* sysname_len = NULL; /* use strlen for determining len */ 76 static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ 77 static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ 78 static u16_t sysname_bufsize = 0; /* 0=not writable */ 79 80 /** mib-2.system.sysLocation */ 81 static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; 82 static const u8_t* syslocation = syslocation_default; 83 static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ 84 static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ 85 static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ 86 static u16_t syslocation_bufsize = 0; /* 0=not writable */ 87 88 /** 89 * @ingroup snmp_mib2 90 * Initializes sysDescr pointers. 91 * 92 * @param str if non-NULL then copy str pointer 93 * @param len points to string length, excluding zero terminator 94 */ 95 void 96 snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) 97 { 98 if (str != NULL) { 99 sysdescr = str; 100 sysdescr_len = len; 101 } 102 } 103 104 /** 105 * @ingroup snmp_mib2 106 * Initializes sysContact pointers 107 * 108 * @param ocstr if non-NULL then copy str pointer 109 * @param ocstrlen points to string length, excluding zero terminator. 110 * if set to NULL it is assumed that ocstr is NULL-terminated. 111 * @param bufsize size of the buffer in bytes. 112 * (this is required because the buffer can be overwritten by snmp-set) 113 * if ocstrlen is NULL buffer needs space for terminating 0 byte. 114 * otherwise complete buffer is used for string. 115 * if bufsize is set to 0, the value is regarded as read-only. 116 */ 117 void 118 snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) 119 { 120 if (ocstr != NULL) { 121 syscontact = ocstr; 122 syscontact_wr = ocstr; 123 syscontact_len = ocstrlen; 124 syscontact_wr_len = ocstrlen; 125 syscontact_bufsize = bufsize; 126 } 127 } 128 129 /** 130 * @ingroup snmp_mib2 131 * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory 132 */ 133 void 134 snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) 135 { 136 if (ocstr != NULL) { 137 syscontact = ocstr; 138 syscontact_len = ocstrlen; 139 syscontact_wr = NULL; 140 syscontact_wr_len = NULL; 141 syscontact_bufsize = 0; 142 } 143 } 144 145 146 /** 147 * @ingroup snmp_mib2 148 * Initializes sysName pointers 149 * 150 * @param ocstr if non-NULL then copy str pointer 151 * @param ocstrlen points to string length, excluding zero terminator. 152 * if set to NULL it is assumed that ocstr is NULL-terminated. 153 * @param bufsize size of the buffer in bytes. 154 * (this is required because the buffer can be overwritten by snmp-set) 155 * if ocstrlen is NULL buffer needs space for terminating 0 byte. 156 * otherwise complete buffer is used for string. 157 * if bufsize is set to 0, the value is regarded as read-only. 158 */ 159 void 160 snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) 161 { 162 if (ocstr != NULL) { 163 sysname = ocstr; 164 sysname_wr = ocstr; 165 sysname_len = ocstrlen; 166 sysname_wr_len = ocstrlen; 167 sysname_bufsize = bufsize; 168 } 169 } 170 171 /** 172 * @ingroup snmp_mib2 173 * see \ref snmp_mib2_set_sysname but set pointer to readonly memory 174 */ 175 void 176 snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) 177 { 178 if (ocstr != NULL) { 179 sysname = ocstr; 180 sysname_len = ocstrlen; 181 sysname_wr = NULL; 182 sysname_wr_len = NULL; 183 sysname_bufsize = 0; 184 } 185 } 186 187 /** 188 * @ingroup snmp_mib2 189 * Initializes sysLocation pointers 190 * 191 * @param ocstr if non-NULL then copy str pointer 192 * @param ocstrlen points to string length, excluding zero terminator. 193 * if set to NULL it is assumed that ocstr is NULL-terminated. 194 * @param bufsize size of the buffer in bytes. 195 * (this is required because the buffer can be overwritten by snmp-set) 196 * if ocstrlen is NULL buffer needs space for terminating 0 byte. 197 * otherwise complete buffer is used for string. 198 * if bufsize is set to 0, the value is regarded as read-only. 199 */ 200 void 201 snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) 202 { 203 if (ocstr != NULL) { 204 syslocation = ocstr; 205 syslocation_wr = ocstr; 206 syslocation_len = ocstrlen; 207 syslocation_wr_len = ocstrlen; 208 syslocation_bufsize = bufsize; 209 } 210 } 211 212 /** 213 * @ingroup snmp_mib2 214 * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory 215 */ 216 void 217 snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) 218 { 219 if (ocstr != NULL) { 220 syslocation = ocstr; 221 syslocation_len = ocstrlen; 222 syslocation_wr = NULL; 223 syslocation_wr_len = NULL; 224 syslocation_bufsize = 0; 225 } 226 } 227 228 229 static s16_t 230 system_get_value(const struct snmp_scalar_array_node_def *node, void *value) 231 { 232 const u8_t* var = NULL; 233 const s16_t* var_len; 234 u16_t result; 235 236 switch (node->oid) { 237 case 1: /* sysDescr */ 238 var = sysdescr; 239 var_len = (const s16_t*)sysdescr_len; 240 break; 241 case 2: /* sysObjectID */ 242 { 243 const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); 244 MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); 245 return dev_enterprise_oid->len * sizeof(u32_t); 246 } 247 case 3: /* sysUpTime */ 248 MIB2_COPY_SYSUPTIME_TO((u32_t*)value); 249 return sizeof(u32_t); 250 case 4: /* sysContact */ 251 var = syscontact; 252 var_len = (const s16_t*)syscontact_len; 253 break; 254 case 5: /* sysName */ 255 var = sysname; 256 var_len = (const s16_t*)sysname_len; 257 break; 258 case 6: /* sysLocation */ 259 var = syslocation; 260 var_len = (const s16_t*)syslocation_len; 261 break; 262 case 7: /* sysServices */ 263 *(s32_t*)value = SNMP_SYSSERVICES; 264 return sizeof(s32_t); 265 default: 266 LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); 267 return 0; 268 } 269 270 /* handle string values (OID 1,4,5 and 6) */ 271 LWIP_ASSERT("", (value != NULL)); 272 if (var_len == NULL) { 273 result = (s16_t)strlen((const char*)var); 274 } else { 275 result = *var_len; 276 } 277 MEMCPY(value, var, result); 278 return result; 279 } 280 281 static snmp_err_t 282 system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) 283 { 284 snmp_err_t ret = SNMP_ERR_WRONGVALUE; 285 const u16_t* var_bufsize = NULL; 286 const u16_t* var_wr_len; 287 288 LWIP_UNUSED_ARG(value); 289 290 switch (node->oid) { 291 case 4: /* sysContact */ 292 var_bufsize = &syscontact_bufsize; 293 var_wr_len = syscontact_wr_len; 294 break; 295 case 5: /* sysName */ 296 var_bufsize = &sysname_bufsize; 297 var_wr_len = sysname_wr_len; 298 break; 299 case 6: /* sysLocation */ 300 var_bufsize = &syslocation_bufsize; 301 var_wr_len = syslocation_wr_len; 302 break; 303 default: 304 LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); 305 return ret; 306 } 307 308 /* check if value is writable at all */ 309 if (*var_bufsize > 0) { 310 if (var_wr_len == NULL) { 311 /* we have to take the terminating 0 into account */ 312 if (len < *var_bufsize) { 313 ret = SNMP_ERR_NOERROR; 314 } 315 } else { 316 if (len <= *var_bufsize) { 317 ret = SNMP_ERR_NOERROR; 318 } 319 } 320 } else { 321 ret = SNMP_ERR_NOTWRITABLE; 322 } 323 324 return ret; 325 } 326 327 static snmp_err_t 328 system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) 329 { 330 u8_t* var_wr = NULL; 331 u16_t* var_wr_len; 332 333 switch (node->oid) { 334 case 4: /* sysContact */ 335 var_wr = syscontact_wr; 336 var_wr_len = syscontact_wr_len; 337 break; 338 case 5: /* sysName */ 339 var_wr = sysname_wr; 340 var_wr_len = sysname_wr_len; 341 break; 342 case 6: /* sysLocation */ 343 var_wr = syslocation_wr; 344 var_wr_len = syslocation_wr_len; 345 break; 346 default: 347 LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); 348 return SNMP_ERR_GENERROR; 349 } 350 351 /* no need to check size of target buffer, this was already done in set_test method */ 352 LWIP_ASSERT("", var_wr != NULL); 353 MEMCPY(var_wr, value, len); 354 355 if (var_wr_len == NULL) { 356 /* add terminating 0 */ 357 var_wr[len] = 0; 358 } else { 359 *var_wr_len = len; 360 } 361 362 return SNMP_ERR_NOERROR; 363 } 364 365 static const struct snmp_scalar_array_node_def system_nodes[] = { 366 {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ 367 {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ 368 {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ 369 {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ 370 {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ 371 {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ 372 {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ 373 }; 374 375 const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); 376 377 #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ 378