41 changed files with 0 additions and 15755 deletions
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science. |
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission.
|
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se> |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/httpd_opts.h" |
||||
#include "lwip/def.h" |
||||
#include "lwip/apps/fs.h" |
||||
#include "fsdata.h" |
||||
#include <string.h> |
||||
|
||||
|
||||
#if HTTPD_USE_CUSTOM_FSDATA |
||||
#include "fsdata_custom.c" |
||||
#else /* HTTPD_USE_CUSTOM_FSDATA */ |
||||
#include "fsdata.c" |
||||
#endif /* HTTPD_USE_CUSTOM_FSDATA */ |
||||
|
||||
/*-----------------------------------------------------------------------------------*/ |
||||
|
||||
#if LWIP_HTTPD_CUSTOM_FILES |
||||
int fs_open_custom(struct fs_file *file, const char *name); |
||||
void fs_close_custom(struct fs_file *file); |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
u8_t fs_canread_custom(struct fs_file *file); |
||||
u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); |
||||
int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); |
||||
#else /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
int fs_read_custom(struct fs_file *file, char *buffer, int count); |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
#endif /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
|
||||
/*-----------------------------------------------------------------------------------*/ |
||||
err_t |
||||
fs_open(struct fs_file *file, const char *name) |
||||
{ |
||||
const struct fsdata_file *f; |
||||
|
||||
if ((file == NULL) || (name == NULL)) { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
#if LWIP_HTTPD_CUSTOM_FILES |
||||
if (fs_open_custom(file, name)) { |
||||
file->is_custom_file = 1; |
||||
return ERR_OK; |
||||
} |
||||
file->is_custom_file = 0; |
||||
#endif /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
|
||||
for (f = FS_ROOT; f != NULL; f = f->next) { |
||||
if (!strcmp(name, (const char *)f->name)) { |
||||
file->data = (const char *)f->data; |
||||
file->len = f->len; |
||||
file->index = f->len; |
||||
file->pextension = NULL; |
||||
file->flags = f->flags; |
||||
#if HTTPD_PRECALCULATED_CHECKSUM |
||||
file->chksum_count = f->chksum_count; |
||||
file->chksum = f->chksum; |
||||
#endif /* HTTPD_PRECALCULATED_CHECKSUM */ |
||||
#if LWIP_HTTPD_FILE_STATE |
||||
file->state = fs_state_init(file, name); |
||||
#endif /* #if LWIP_HTTPD_FILE_STATE */ |
||||
return ERR_OK; |
||||
} |
||||
} |
||||
/* file not found */ |
||||
return ERR_VAL; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------------------*/ |
||||
void |
||||
fs_close(struct fs_file *file) |
||||
{ |
||||
#if LWIP_HTTPD_CUSTOM_FILES |
||||
if (file->is_custom_file) { |
||||
fs_close_custom(file); |
||||
} |
||||
#endif /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
#if LWIP_HTTPD_FILE_STATE |
||||
fs_state_free(file, file->state); |
||||
#endif /* #if LWIP_HTTPD_FILE_STATE */ |
||||
LWIP_UNUSED_ARG(file); |
||||
} |
||||
/*-----------------------------------------------------------------------------------*/ |
||||
#if LWIP_HTTPD_DYNAMIC_FILE_READ |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
int |
||||
fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) |
||||
#else /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
int |
||||
fs_read(struct fs_file *file, char *buffer, int count) |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
{ |
||||
int read; |
||||
if(file->index == file->len) { |
||||
return FS_READ_EOF; |
||||
} |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
LWIP_UNUSED_ARG(callback_fn); |
||||
LWIP_UNUSED_ARG(callback_arg); |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
#if LWIP_HTTPD_CUSTOM_FILES |
||||
if (file->is_custom_file) { |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); |
||||
#else /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
return fs_read_custom(file, buffer, count); |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
} |
||||
#endif /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
|
||||
read = file->len - file->index; |
||||
if(read > count) { |
||||
read = count; |
||||
} |
||||
|
||||
MEMCPY(buffer, (file->data + file->index), read); |
||||
file->index += read; |
||||
|
||||
return(read); |
||||
} |
||||
#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ |
||||
/*-----------------------------------------------------------------------------------*/ |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
int |
||||
fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) |
||||
{ |
||||
if (file != NULL) { |
||||
#if LWIP_HTTPD_FS_ASYNC_READ |
||||
#if LWIP_HTTPD_CUSTOM_FILES |
||||
if (!fs_canread_custom(file)) { |
||||
if (fs_wait_read_custom(file, callback_fn, callback_arg)) { |
||||
return 0; |
||||
} |
||||
} |
||||
#else /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
LWIP_UNUSED_ARG(callback_fn); |
||||
LWIP_UNUSED_ARG(callback_arg); |
||||
#endif /* LWIP_HTTPD_CUSTOM_FILES */ |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
} |
||||
return 1; |
||||
} |
||||
#endif /* LWIP_HTTPD_FS_ASYNC_READ */ |
||||
/*-----------------------------------------------------------------------------------*/ |
||||
int |
||||
fs_bytes_left(struct fs_file *file) |
||||
{ |
||||
return file->len - file->index; |
||||
} |
||||
@ -1,21 +0,0 @@
|
||||
<html> |
||||
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head> |
||||
<body bgcolor="white" text="black"> |
||||
|
||||
<table width="100%"> |
||||
<tr valign="top"><td width="80"> |
||||
<a href="http://www.sics.se/"><img src="/img/sics.gif" |
||||
border="0" alt="SICS logo" title="SICS logo"></a> |
||||
</td><td width="500"> |
||||
<h1>lwIP - A Lightweight TCP/IP Stack</h1> |
||||
<h2>404 - Page not found</h2> |
||||
<p> |
||||
Sorry, the page you are requesting was not found on this |
||||
server. |
||||
</p> |
||||
</td><td> |
||||
|
||||
</td></tr> |
||||
</table> |
||||
</body> |
||||
</html> |
||||
|
Before Width: | Height: | Size: 724 B |
@ -1,47 +0,0 @@
|
||||
<html> |
||||
<head><title>lwIP - A Lightweight TCP/IP Stack</title></head> |
||||
<body bgcolor="white" text="black"> |
||||
|
||||
<table width="100%"> |
||||
<tr valign="top"><td width="80"> |
||||
<a href="http://www.sics.se/"><img src="/img/sics.gif" |
||||
border="0" alt="SICS logo" title="SICS logo"></a> |
||||
</td><td width="500"> |
||||
<h1>lwIP - A Lightweight TCP/IP Stack</h1> |
||||
<p> |
||||
The web page you are watching was served by a simple web |
||||
server running on top of the lightweight TCP/IP stack <a |
||||
href="http://www.sics.se/~adam/lwip/">lwIP</a>. |
||||
</p> |
||||
<p> |
||||
lwIP is an open source implementation of the TCP/IP |
||||
protocol suite that was originally written by <a |
||||
href="http://www.sics.se/~adam/lwip/">Adam Dunkels |
||||
of the Swedish Institute of Computer Science</a> but now is |
||||
being actively developed by a team of developers |
||||
distributed world-wide. Since it's release, lwIP has |
||||
spurred a lot of interest and has been ported to several |
||||
platforms and operating systems. lwIP can be used either |
||||
with or without an underlying OS. |
||||
</p> |
||||
<p> |
||||
The focus of the lwIP TCP/IP implementation is to reduce |
||||
the RAM usage while still having a full scale TCP. This |
||||
makes lwIP suitable for use in embedded systems with tens |
||||
of kilobytes of free RAM and room for around 40 kilobytes |
||||
of code ROM. |
||||
</p> |
||||
<p> |
||||
More information about lwIP can be found at the lwIP |
||||
homepage at <a |
||||
href="http://savannah.nongnu.org/projects/lwip/">http://savannah.nongnu.org/projects/lwip/</a> |
||||
or at the lwIP wiki at <a |
||||
href="http://lwip.wikia.com/">http://lwip.wikia.com/</a>. |
||||
</p> |
||||
</td><td> |
||||
|
||||
</td></tr> |
||||
</table> |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,298 +0,0 @@
|
||||
#include "lwip/apps/fs.h" |
||||
#include "lwip/def.h" |
||||
#include "fsdata.h" |
||||
|
||||
|
||||
#define file_NULL (struct fsdata_file *) NULL |
||||
|
||||
|
||||
static const unsigned int dummy_align__img_sics_gif = 0; |
||||
static const unsigned char data__img_sics_gif[] = { |
||||
/* /img/sics.gif (14 chars) */ |
||||
0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, |
||||
|
||||
/* HTTP header */ |
||||
/* "HTTP/1.0 200 OK
|
||||
" (17 bytes) */ |
||||
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, |
||||
0x0a, |
||||
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||
" (63 bytes) */ |
||||
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, |
||||
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, |
||||
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, |
||||
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, |
||||
/* "Content-type: image/gif
|
||||
|
||||
" (27 bytes) */ |
||||
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, |
||||
0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, |
||||
/* raw file data (724 bytes) */ |
||||
0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, |
||||
0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, |
||||
0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, |
||||
0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, |
||||
0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, |
||||
0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, |
||||
0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, |
||||
0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, |
||||
0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, |
||||
0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, |
||||
0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, |
||||
0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, |
||||
0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, |
||||
0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, |
||||
0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, |
||||
0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, |
||||
0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, |
||||
0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, |
||||
0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, |
||||
0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, |
||||
0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, |
||||
0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, |
||||
0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, |
||||
0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, |
||||
0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, |
||||
0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, |
||||
0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, |
||||
0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, |
||||
0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, |
||||
0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, |
||||
0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, |
||||
0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, |
||||
0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, |
||||
0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, |
||||
0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, |
||||
0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, |
||||
0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, |
||||
0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, |
||||
0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, |
||||
0x41,0x00,0x00,0x3b,}; |
||||
|
||||
static const unsigned int dummy_align__404_html = 1; |
||||
static const unsigned char data__404_html[] = { |
||||
/* /404.html (10 chars) */ |
||||
0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, |
||||
|
||||
/* HTTP header */ |
||||
/* "HTTP/1.0 404 File not found
|
||||
" (29 bytes) */ |
||||
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, |
||||
0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, |
||||
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||
" (63 bytes) */ |
||||
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, |
||||
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, |
||||
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, |
||||
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, |
||||
/* "Content-type: text/html
|
||||
|
||||
" (27 bytes) */ |
||||
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, |
||||
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, |
||||
/* raw file data (565 bytes) */ |
||||
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, |
||||
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, |
||||
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, |
||||
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, |
||||
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, |
||||
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, |
||||
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, |
||||
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, |
||||
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, |
||||
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, |
||||
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, |
||||
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, |
||||
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, |
||||
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, |
||||
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, |
||||
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, |
||||
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, |
||||
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, |
||||
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, |
||||
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, |
||||
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, |
||||
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, |
||||
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, |
||||
0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, |
||||
0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, |
||||
0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, |
||||
0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, |
||||
0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, |
||||
0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, |
||||
0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, |
||||
0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, |
||||
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, |
||||
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, |
||||
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, |
||||
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, |
||||
0x6d,0x6c,0x3e,0x0d,0x0a,}; |
||||
|
||||
static const unsigned int dummy_align__index_html = 2; |
||||
static const unsigned char data__index_html[] = { |
||||
/* /index.html (12 chars) */ |
||||
0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, |
||||
|
||||
/* HTTP header */ |
||||
/* "HTTP/1.0 200 OK
|
||||
" (17 bytes) */ |
||||
0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, |
||||
0x0a, |
||||
/* "Server: lwIP/1.3.1 (http://savannah.nongnu.org/projects/lwip)
|
||||
" (63 bytes) */ |
||||
0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x31,0x2e,0x33, |
||||
0x2e,0x31,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e, |
||||
0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70, |
||||
0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, |
||||
/* "Content-type: text/html
|
||||
|
||||
" (27 bytes) */ |
||||
0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x74,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, |
||||
0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, |
||||
/* raw file data (1751 bytes) */ |
||||
0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, |
||||
0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, |
||||
0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, |
||||
0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, |
||||
0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, |
||||
0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, |
||||
0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, |
||||
0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, |
||||
0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, |
||||
0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, |
||||
0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, |
||||
0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, |
||||
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, |
||||
0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, |
||||
0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, |
||||
0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, |
||||
0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, |
||||
0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, |
||||
0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, |
||||
0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, |
||||
0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, |
||||
0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, |
||||
0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, |
||||
0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, |
||||
0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, |
||||
0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, |
||||
0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, |
||||
0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, |
||||
0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, |
||||
0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, |
||||
0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, |
||||
0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, |
||||
0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, |
||||
0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, |
||||
0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, |
||||
0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, |
||||
0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, |
||||
0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, |
||||
0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, |
||||
0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, |
||||
0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, |
||||
0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, |
||||
0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, |
||||
0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, |
||||
0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, |
||||
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, |
||||
0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, |
||||
0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, |
||||
0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, |
||||
0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, |
||||
0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, |
||||
0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, |
||||
0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, |
||||
0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, |
||||
0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, |
||||
0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, |
||||
0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, |
||||
0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, |
||||
0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, |
||||
0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, |
||||
0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, |
||||
0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, |
||||
0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, |
||||
0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, |
||||
0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, |
||||
0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, |
||||
0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, |
||||
0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, |
||||
0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, |
||||
0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, |
||||
0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, |
||||
0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, |
||||
0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, |
||||
0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, |
||||
0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, |
||||
0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, |
||||
0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, |
||||
0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, |
||||
0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, |
||||
0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, |
||||
0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, |
||||
0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, |
||||
0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, |
||||
0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, |
||||
0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, |
||||
0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, |
||||
0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, |
||||
0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, |
||||
0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, |
||||
0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, |
||||
0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, |
||||
0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, |
||||
0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, |
||||
0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, |
||||
0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, |
||||
0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, |
||||
0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, |
||||
0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, |
||||
0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, |
||||
0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, |
||||
0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, |
||||
0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, |
||||
0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, |
||||
0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, |
||||
0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, |
||||
0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, |
||||
0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, |
||||
0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, |
||||
0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, |
||||
0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; |
||||
|
||||
|
||||
|
||||
const struct fsdata_file file__img_sics_gif[] = { { |
||||
file_NULL, |
||||
data__img_sics_gif, |
||||
data__img_sics_gif + 16, |
||||
sizeof(data__img_sics_gif) - 16, |
||||
1, |
||||
}}; |
||||
|
||||
const struct fsdata_file file__404_html[] = { { |
||||
file__img_sics_gif, |
||||
data__404_html, |
||||
data__404_html + 12, |
||||
sizeof(data__404_html) - 12, |
||||
1, |
||||
}}; |
||||
|
||||
const struct fsdata_file file__index_html[] = { { |
||||
file__404_html, |
||||
data__index_html, |
||||
data__index_html + 12, |
||||
sizeof(data__index_html) - 12, |
||||
1, |
||||
}}; |
||||
|
||||
#define FS_ROOT file__index_html |
||||
#define FS_NUMFILES 3 |
||||
|
||||
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science. |
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission.
|
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se> |
||||
* |
||||
*/ |
||||
#ifndef LWIP_FSDATA_H |
||||
#define LWIP_FSDATA_H |
||||
|
||||
#include "lwip/apps/httpd_opts.h" |
||||
#include "lwip/apps/fs.h" |
||||
|
||||
struct fsdata_file { |
||||
const struct fsdata_file *next; |
||||
const unsigned char *name; |
||||
const unsigned char *data; |
||||
int len; |
||||
u8_t flags; |
||||
#if HTTPD_PRECALCULATED_CHECKSUM |
||||
u16_t chksum_count; |
||||
const struct fsdata_chksum *chksum; |
||||
#endif /* HTTPD_PRECALCULATED_CHECKSUM */ |
||||
}; |
||||
|
||||
#endif /* LWIP_FSDATA_H */ |
||||
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
#ifndef LWIP_HTTPD_STRUCTS_H |
||||
#define LWIP_HTTPD_STRUCTS_H |
||||
|
||||
#include "lwip/apps/httpd.h" |
||||
|
||||
#if LWIP_HTTPD_DYNAMIC_HEADERS |
||||
/** This struct is used for a list of HTTP header strings for various
|
||||
* filename extensions. */ |
||||
typedef struct |
||||
{ |
||||
const char *extension; |
||||
const char *content_type; |
||||
} tHTTPHeader; |
||||
|
||||
/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and
|
||||
* RFC 2616 HTTP/1.1 for header field definitions) */ |
||||
static const char * const g_psHTTPHeaderStrings[] = |
||||
{ |
||||
"HTTP/1.0 200 OK\r\n", |
||||
"HTTP/1.0 404 File not found\r\n", |
||||
"HTTP/1.0 400 Bad Request\r\n", |
||||
"HTTP/1.0 501 Not Implemented\r\n", |
||||
"HTTP/1.1 200 OK\r\n", |
||||
"HTTP/1.1 404 File not found\r\n", |
||||
"HTTP/1.1 400 Bad Request\r\n", |
||||
"HTTP/1.1 501 Not Implemented\r\n", |
||||
"Content-Length: ", |
||||
"Connection: Close\r\n", |
||||
"Connection: keep-alive\r\n", |
||||
"Connection: keep-alive\r\nContent-Length: ", |
||||
"Server: "HTTPD_SERVER_AGENT"\r\n", |
||||
"\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n" |
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE |
||||
,"Connection: keep-alive\r\nContent-Length: 77\r\n\r\n<html><body><h2>404: The requested file cannot be found.</h2></body></html>\r\n" |
||||
#endif |
||||
}; |
||||
|
||||
/* Indexes into the g_psHTTPHeaderStrings array */ |
||||
#define HTTP_HDR_OK 0 /* 200 OK */ |
||||
#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ |
||||
#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ |
||||
#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ |
||||
#define HTTP_HDR_OK_11 4 /* 200 OK */ |
||||
#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ |
||||
#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ |
||||
#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ |
||||
#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ |
||||
#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ |
||||
#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ |
||||
#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ |
||||
#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ |
||||
#define DEFAULT_404_HTML 13 /* default 404 body */ |
||||
#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE |
||||
#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ |
||||
#endif |
||||
|
||||
|
||||
#define HTTP_HDR_HTML "Content-type: text/html\r\n\r\n" |
||||
#define HTTP_HDR_SSI "Content-type: text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n" |
||||
#define HTTP_HDR_GIF "Content-type: image/gif\r\n\r\n" |
||||
#define HTTP_HDR_PNG "Content-type: image/png\r\n\r\n" |
||||
#define HTTP_HDR_JPG "Content-type: image/jpeg\r\n\r\n" |
||||
#define HTTP_HDR_BMP "Content-type: image/bmp\r\n\r\n" |
||||
#define HTTP_HDR_ICO "Content-type: image/x-icon\r\n\r\n" |
||||
#define HTTP_HDR_APP "Content-type: application/octet-stream\r\n\r\n" |
||||
#define HTTP_HDR_JS "Content-type: application/javascript\r\n\r\n" |
||||
#define HTTP_HDR_RA "Content-type: application/javascript\r\n\r\n" |
||||
#define HTTP_HDR_CSS "Content-type: text/css\r\n\r\n" |
||||
#define HTTP_HDR_SWF "Content-type: application/x-shockwave-flash\r\n\r\n" |
||||
#define HTTP_HDR_XML "Content-type: text/xml\r\n\r\n" |
||||
#define HTTP_HDR_PDF "Content-type: application/pdf\r\n\r\n" |
||||
#define HTTP_HDR_JSON "Content-type: application/json\r\n\r\n" |
||||
|
||||
#define HTTP_HDR_DEFAULT_TYPE "Content-type: text/plain\r\n\r\n" |
||||
|
||||
/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES
|
||||
* and http://www.iana.org/assignments/media-types for registered content types
|
||||
* and subtypes) */ |
||||
static const tHTTPHeader g_psHTTPHeaders[] = |
||||
{ |
||||
{ "html", HTTP_HDR_HTML}, |
||||
{ "htm", HTTP_HDR_HTML}, |
||||
{ "shtml",HTTP_HDR_SSI}, |
||||
{ "shtm", HTTP_HDR_SSI}, |
||||
{ "ssi", HTTP_HDR_SSI}, |
||||
{ "gif", HTTP_HDR_GIF}, |
||||
{ "png", HTTP_HDR_PNG}, |
||||
{ "jpg", HTTP_HDR_JPG}, |
||||
{ "bmp", HTTP_HDR_BMP}, |
||||
{ "ico", HTTP_HDR_ICO}, |
||||
{ "class",HTTP_HDR_APP}, |
||||
{ "cls", HTTP_HDR_APP}, |
||||
{ "js", HTTP_HDR_JS}, |
||||
{ "ram", HTTP_HDR_RA}, |
||||
{ "css", HTTP_HDR_CSS}, |
||||
{ "swf", HTTP_HDR_SWF}, |
||||
{ "xml", HTTP_HDR_XML}, |
||||
{ "xsl", HTTP_HDR_XML}, |
||||
{ "pdf", HTTP_HDR_PDF}, |
||||
{ "json", HTTP_HDR_JSON} |
||||
}; |
||||
|
||||
#define NUM_HTTP_HEADERS (sizeof(g_psHTTPHeaders) / sizeof(tHTTPHeader)) |
||||
|
||||
#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ |
||||
|
||||
#if LWIP_HTTPD_SSI |
||||
static const char * const g_pcSSIExtensions[] = { |
||||
".shtml", ".shtm", ".ssi", ".xml" |
||||
}; |
||||
#define NUM_SHTML_EXTENSIONS (sizeof(g_pcSSIExtensions) / sizeof(const char *)) |
||||
#endif /* LWIP_HTTPD_SSI */ |
||||
|
||||
#endif /* LWIP_HTTPD_STRUCTS_H */ |
||||
@ -1,97 +0,0 @@
|
||||
#!/usr/bin/perl |
||||
|
||||
open(OUTPUT, "> fsdata.c"); |
||||
|
||||
chdir("fs"); |
||||
open(FILES, "find . -type f |"); |
||||
|
||||
while($file = <FILES>) { |
||||
|
||||
# Do not include files in CVS directories nor backup files. |
||||
if($file =~ /(CVS|~)/) { |
||||
next; |
||||
} |
||||
|
||||
chop($file); |
||||
|
||||
open(HEADER, "> /tmp/header") || die $!; |
||||
if($file =~ /404/) { |
||||
print(HEADER "HTTP/1.0 404 File not found\r\n"); |
||||
} else { |
||||
print(HEADER "HTTP/1.0 200 OK\r\n"); |
||||
} |
||||
print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); |
||||
if($file =~ /\.html$/) { |
||||
print(HEADER "Content-type: text/html\r\n"); |
||||
} elsif($file =~ /\.gif$/) { |
||||
print(HEADER "Content-type: image/gif\r\n"); |
||||
} elsif($file =~ /\.png$/) { |
||||
print(HEADER "Content-type: image/png\r\n"); |
||||
} elsif($file =~ /\.jpg$/) { |
||||
print(HEADER "Content-type: image/jpeg\r\n"); |
||||
} elsif($file =~ /\.class$/) { |
||||
print(HEADER "Content-type: application/octet-stream\r\n"); |
||||
} elsif($file =~ /\.ram$/) { |
||||
print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); |
||||
} else { |
||||
print(HEADER "Content-type: text/plain\r\n"); |
||||
} |
||||
print(HEADER "\r\n"); |
||||
close(HEADER); |
||||
|
||||
unless($file =~ /\.plain$/ || $file =~ /cgi/) { |
||||
system("cat /tmp/header $file > /tmp/file"); |
||||
} else { |
||||
system("cp $file /tmp/file"); |
||||
} |
||||
|
||||
open(FILE, "/tmp/file"); |
||||
unlink("/tmp/file"); |
||||
unlink("/tmp/header"); |
||||
|
||||
$file =~ s/\.//; |
||||
$fvar = $file; |
||||
$fvar =~ s-/-_-g; |
||||
$fvar =~ s-\.-_-g; |
||||
print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); |
||||
print(OUTPUT "\t/* $file */\n\t"); |
||||
for($j = 0; $j < length($file); $j++) { |
||||
printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); |
||||
} |
||||
printf(OUTPUT "0,\n"); |
||||
|
||||
|
||||
$i = 0; |
||||
while(read(FILE, $data, 1)) { |
||||
if($i == 0) { |
||||
print(OUTPUT "\t"); |
||||
} |
||||
printf(OUTPUT "%#02x, ", unpack("C", $data)); |
||||
$i++; |
||||
if($i == 10) { |
||||
print(OUTPUT "\n"); |
||||
$i = 0; |
||||
} |
||||
} |
||||
print(OUTPUT "};\n\n"); |
||||
close(FILE); |
||||
push(@fvars, $fvar); |
||||
push(@files, $file); |
||||
} |
||||
|
||||
for($i = 0; $i < @fvars; $i++) { |
||||
$file = $files[$i]; |
||||
$fvar = $fvars[$i]; |
||||
|
||||
if($i == 0) { |
||||
$prevfile = "NULL"; |
||||
} else { |
||||
$prevfile = "file" . $fvars[$i - 1]; |
||||
} |
||||
print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); |
||||
print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); |
||||
print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); |
||||
} |
||||
|
||||
print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); |
||||
print(OUTPUT "#define FS_NUMFILES $i\n"); |
||||
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
This directory contains a script ('makefsdata') to create C code suitable for |
||||
httpd for given html pages (or other files) in a directory. |
||||
|
||||
There is also a plain C console application doing the same and extended a bit. |
||||
|
||||
Usage: htmlgen [targetdir] [-s] [-i]s |
||||
targetdir: relative or absolute path to files to convert |
||||
switch -s: toggle processing of subdirectories (default is on) |
||||
switch -e: exclude HTTP header from file (header is created at runtime, default is on) |
||||
switch -11: include HTTP 1.1 header (1.0 is default) |
||||
|
||||
if targetdir not specified, makefsdata will attempt to |
||||
process files in subdirectory 'fs'. |
||||
@ -1,662 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* lwIP iPerf server implementation |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup iperf Iperf server |
||||
* @ingroup apps |
||||
* |
||||
* This is a simple performance measuring server to check your bandwith using |
||||
* iPerf2 on a PC as client. |
||||
* It is currently a minimal implementation providing an IPv4 TCP server only. |
||||
* |
||||
* @todo: implement UDP mode and IPv6 |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Simon Goldschmidt |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Simon Goldschmidt |
||||
*/ |
||||
|
||||
#include "lwip/apps/lwiperf.h" |
||||
|
||||
#include "lwip/tcp.h" |
||||
#include "lwip/sys.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
/* Currently, only TCP-over-IPv4 is implemented (does iperf support IPv6 anyway?) */ |
||||
#if LWIP_IPV4 && LWIP_TCP |
||||
|
||||
/** Specify the idle timeout (in seconds) after that the test fails */ |
||||
#ifndef LWIPERF_TCP_MAX_IDLE_SEC |
||||
#define LWIPERF_TCP_MAX_IDLE_SEC 10U |
||||
#endif |
||||
#if LWIPERF_TCP_MAX_IDLE_SEC > 255 |
||||
#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t |
||||
#endif |
||||
|
||||
/* File internal memory allocation (struct lwiperf_*): this defaults to
|
||||
the heap */ |
||||
#ifndef LWIPERF_ALLOC |
||||
#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) |
||||
#define LWIPERF_FREE(type, item) mem_free(item) |
||||
#endif |
||||
|
||||
/** If this is 1, check that received data has the correct format */ |
||||
#ifndef LWIPERF_CHECK_RX_DATA |
||||
#define LWIPERF_CHECK_RX_DATA 0 |
||||
#endif |
||||
|
||||
/** This is the Iperf settings struct sent from the client */ |
||||
typedef struct _lwiperf_settings { |
||||
#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 |
||||
#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 |
||||
u32_t flags; |
||||
u32_t num_threads; /* unused for now */ |
||||
u32_t remote_port; |
||||
u32_t buffer_len; /* unused for now */ |
||||
u32_t win_band; /* TCP window / UDP rate: unused for now */ |
||||
u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ |
||||
} lwiperf_settings_t; |
||||
|
||||
/** Basic connection handle */ |
||||
struct _lwiperf_state_base; |
||||
typedef struct _lwiperf_state_base lwiperf_state_base_t; |
||||
struct _lwiperf_state_base { |
||||
/* 1=tcp, 0=udp */ |
||||
u8_t tcp; |
||||
/* 1=server, 0=client */ |
||||
u8_t server; |
||||
lwiperf_state_base_t* next; |
||||
lwiperf_state_base_t* related_server_state; |
||||
}; |
||||
|
||||
/** Connection handle for a TCP iperf session */ |
||||
typedef struct _lwiperf_state_tcp { |
||||
lwiperf_state_base_t base; |
||||
struct tcp_pcb* server_pcb; |
||||
struct tcp_pcb* conn_pcb; |
||||
u32_t time_started; |
||||
lwiperf_report_fn report_fn; |
||||
void* report_arg; |
||||
u8_t poll_count; |
||||
u8_t next_num; |
||||
u32_t bytes_transferred; |
||||
lwiperf_settings_t settings; |
||||
u8_t have_settings_buf; |
||||
} lwiperf_state_tcp_t; |
||||
|
||||
/** List of active iperf sessions */ |
||||
static lwiperf_state_base_t* lwiperf_all_connections; |
||||
/** A const buffer to send from: we want to measure sending, not copying! */ |
||||
static const u8_t lwiperf_txbuf_const[1600] = { |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', |
||||
}; |
||||
|
||||
static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); |
||||
static void lwiperf_tcp_err(void *arg, err_t err); |
||||
|
||||
/** Add an iperf session to the 'active' list */ |
||||
static void |
||||
lwiperf_list_add(lwiperf_state_base_t* item) |
||||
{ |
||||
if (lwiperf_all_connections == NULL) { |
||||
lwiperf_all_connections = item; |
||||
} else { |
||||
item = lwiperf_all_connections; |
||||
} |
||||
} |
||||
|
||||
/** Remove an iperf session from the 'active' list */ |
||||
static void |
||||
lwiperf_list_remove(lwiperf_state_base_t* item) |
||||
{ |
||||
lwiperf_state_base_t* prev = NULL; |
||||
lwiperf_state_base_t* iter; |
||||
for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { |
||||
if (iter == item) { |
||||
if (prev == NULL) { |
||||
lwiperf_all_connections = iter->next; |
||||
} else { |
||||
prev->next = item; |
||||
} |
||||
/* @debug: ensure this item is listed only once */ |
||||
for (iter = iter->next; iter != NULL; iter = iter->next) { |
||||
LWIP_ASSERT("duplicate entry", iter != item); |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** Call the report function of an iperf tcp session */ |
||||
static void |
||||
lwip_tcp_conn_report(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) |
||||
{ |
||||
if ((conn != NULL) && (conn->report_fn != NULL)) { |
||||
u32_t now, duration_ms, bandwidth_kbitpsec; |
||||
now = sys_now(); |
||||
duration_ms = now - conn->time_started; |
||||
if (duration_ms == 0) { |
||||
bandwidth_kbitpsec = 0; |
||||
} else { |
||||
bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; |
||||
} |
||||
conn->report_fn(conn->report_arg, report_type, |
||||
&conn->conn_pcb->local_ip, conn->conn_pcb->local_port, |
||||
&conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, |
||||
conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); |
||||
} |
||||
} |
||||
|
||||
/** Close an iperf tcp session */ |
||||
static void |
||||
lwiperf_tcp_close(lwiperf_state_tcp_t* conn, enum lwiperf_report_type report_type) |
||||
{ |
||||
err_t err; |
||||
|
||||
lwip_tcp_conn_report(conn, report_type); |
||||
lwiperf_list_remove(&conn->base); |
||||
if (conn->conn_pcb != NULL) { |
||||
tcp_arg(conn->conn_pcb, NULL); |
||||
tcp_poll(conn->conn_pcb, NULL, 0); |
||||
tcp_sent(conn->conn_pcb, NULL); |
||||
tcp_recv(conn->conn_pcb, NULL); |
||||
tcp_err(conn->conn_pcb, NULL); |
||||
err = tcp_close(conn->conn_pcb); |
||||
if (err != ERR_OK) { |
||||
/* don't want to wait for free memory here... */ |
||||
tcp_abort(conn->conn_pcb); |
||||
} |
||||
} else { |
||||
/* no conn pcb, this is the server pcb */ |
||||
err = tcp_close(conn->server_pcb); |
||||
LWIP_ASSERT("error", err != ERR_OK); |
||||
} |
||||
LWIPERF_FREE(lwiperf_state_tcp_t, conn); |
||||
} |
||||
|
||||
/** Try to send more data on an iperf tcp session */ |
||||
static err_t |
||||
lwiperf_tcp_client_send_more(lwiperf_state_tcp_t* conn) |
||||
{ |
||||
int send_more; |
||||
err_t err; |
||||
u16_t txlen; |
||||
u16_t txlen_max; |
||||
void* txptr; |
||||
u8_t apiflags; |
||||
|
||||
LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); |
||||
|
||||
do { |
||||
send_more = 0; |
||||
if (conn->settings.amount & PP_HTONL(0x80000000)) { |
||||
/* this session is time-limited */ |
||||
u32_t now = sys_now(); |
||||
u32_t diff_ms = now - conn->time_started; |
||||
u32_t time = (u32_t)-(s32_t)htonl(conn->settings.amount); |
||||
u32_t time_ms = time * 10; |
||||
if (diff_ms >= time_ms) { |
||||
/* time specified by the client is over -> close the connection */ |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); |
||||
return ERR_OK; |
||||
} |
||||
} else { |
||||
/* this session is byte-limited */ |
||||
u32_t amount_bytes = htonl(conn->settings.amount); |
||||
/* @todo: this can send up to 1*MSS more than requested... */ |
||||
if (amount_bytes >= conn->bytes_transferred) { |
||||
/* all requested bytes transferred -> close the connection */ |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); |
||||
return ERR_OK; |
||||
} |
||||
} |
||||
|
||||
if (conn->bytes_transferred < 24) { |
||||
/* transmit the settings a first time */ |
||||
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred]; |
||||
txlen_max = (u16_t)(24 - conn->bytes_transferred); |
||||
apiflags = TCP_WRITE_FLAG_COPY; |
||||
} else if (conn->bytes_transferred < 48) { |
||||
/* transmit the settings a second time */ |
||||
txptr = &((u8_t*)&conn->settings)[conn->bytes_transferred - 24]; |
||||
txlen_max = (u16_t)(48 - conn->bytes_transferred); |
||||
apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; |
||||
send_more = 1; |
||||
} else { |
||||
/* transmit data */ |
||||
/* @todo: every x bytes, transmit the settings again */ |
||||
txptr = (void*)(size_t)&lwiperf_txbuf_const[conn->bytes_transferred % 10]; |
||||
txlen_max = TCP_MSS; |
||||
if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ |
||||
txlen_max = TCP_MSS - 24; |
||||
} |
||||
apiflags = 0; /* no copying needed */ |
||||
send_more = 1; |
||||
} |
||||
txlen = txlen_max; |
||||
do { |
||||
err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); |
||||
if (err == ERR_MEM) { |
||||
txlen /= 2; |
||||
} |
||||
} while ((err == ERR_MEM) && (txlen >= (TCP_MSS/2))); |
||||
|
||||
if (err == ERR_OK) { |
||||
conn->bytes_transferred += txlen; |
||||
} else { |
||||
send_more = 0; |
||||
} |
||||
} while(send_more); |
||||
|
||||
tcp_output(conn->conn_pcb); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/** TCP sent callback, try to send more data */ |
||||
static err_t |
||||
lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) |
||||
{ |
||||
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; |
||||
/* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ |
||||
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); |
||||
LWIP_UNUSED_ARG(tpcb); |
||||
LWIP_UNUSED_ARG(len); |
||||
|
||||
conn->poll_count = 0; |
||||
|
||||
return lwiperf_tcp_client_send_more(conn); |
||||
} |
||||
|
||||
/** TCP connected callback (active connection), send data now */ |
||||
static err_t |
||||
lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) |
||||
{ |
||||
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; |
||||
LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); |
||||
LWIP_UNUSED_ARG(tpcb); |
||||
if (err != ERR_OK) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); |
||||
return ERR_OK; |
||||
} |
||||
conn->poll_count = 0; |
||||
conn->time_started = sys_now(); |
||||
return lwiperf_tcp_client_send_more(conn); |
||||
} |
||||
|
||||
/** Start TCP connection back to the client (either parallel or after the
|
||||
* receive test has finished. |
||||
*/ |
||||
static err_t |
||||
lwiperf_tx_start(lwiperf_state_tcp_t* conn) |
||||
{ |
||||
err_t err; |
||||
lwiperf_state_tcp_t* client_conn; |
||||
struct tcp_pcb* newpcb; |
||||
ip_addr_t remote_addr; |
||||
u16_t remote_port; |
||||
|
||||
client_conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); |
||||
if (client_conn == NULL) { |
||||
return ERR_MEM; |
||||
} |
||||
newpcb = tcp_new(); |
||||
if (newpcb == NULL) { |
||||
LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); |
||||
return ERR_MEM; |
||||
} |
||||
|
||||
memcpy(client_conn, conn, sizeof(lwiperf_state_tcp_t)); |
||||
client_conn->base.server = 0; |
||||
client_conn->server_pcb = NULL; |
||||
client_conn->conn_pcb = newpcb; |
||||
client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ |
||||
client_conn->poll_count = 0; |
||||
client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ |
||||
client_conn->bytes_transferred = 0; |
||||
client_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ |
||||
|
||||
tcp_arg(newpcb, client_conn); |
||||
tcp_sent(newpcb, lwiperf_tcp_client_sent); |
||||
tcp_poll(newpcb, lwiperf_tcp_poll, 2U); |
||||
tcp_err(newpcb, lwiperf_tcp_err); |
||||
|
||||
ip_addr_copy(remote_addr, conn->conn_pcb->remote_ip); |
||||
remote_port = (u16_t)htonl(client_conn->settings.remote_port); |
||||
|
||||
err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); |
||||
if (err != ERR_OK) { |
||||
lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); |
||||
return err; |
||||
} |
||||
lwiperf_list_add(&client_conn->base); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/** Receive data on an iperf tcp session */ |
||||
static err_t |
||||
lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) |
||||
{ |
||||
u16_t tot_len; |
||||
u32_t packet_idx; |
||||
struct pbuf* q; |
||||
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; |
||||
|
||||
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); |
||||
LWIP_UNUSED_ARG(tpcb); |
||||
|
||||
if (err != ERR_OK) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); |
||||
return ERR_OK; |
||||
} |
||||
if (p == NULL) { |
||||
/* connection closed -> test done */ |
||||
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == |
||||
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { |
||||
/* client requested transmission after end of test */ |
||||
lwiperf_tx_start(conn); |
||||
} |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); |
||||
return ERR_OK; |
||||
} |
||||
tot_len = p->tot_len; |
||||
|
||||
conn->poll_count = 0; |
||||
|
||||
if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { |
||||
/* wait for 24-byte header */ |
||||
if (p->tot_len < sizeof(lwiperf_settings_t)) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); |
||||
pbuf_free(p); |
||||
return ERR_VAL; |
||||
} |
||||
if (!conn->have_settings_buf) { |
||||
if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); |
||||
pbuf_free(p); |
||||
return ERR_VAL; |
||||
} |
||||
conn->have_settings_buf = 1; |
||||
if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == |
||||
PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { |
||||
/* client requested parallel transmission test */ |
||||
err_t err2 = lwiperf_tx_start(conn); |
||||
if (err2 != ERR_OK) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); |
||||
pbuf_free(p); |
||||
return err2; |
||||
} |
||||
} |
||||
} else { |
||||
if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); |
||||
pbuf_free(p); |
||||
return ERR_VAL; |
||||
} |
||||
} |
||||
conn->bytes_transferred += sizeof(lwiperf_settings_t); |
||||
if (conn->bytes_transferred <= 24) { |
||||
conn->time_started = sys_now(); |
||||
tcp_recved(tpcb, p->tot_len); |
||||
pbuf_free(p); |
||||
return ERR_OK; |
||||
} |
||||
conn->next_num = 4; /* 24 bytes received... */ |
||||
err = pbuf_header(p, -24); |
||||
LWIP_ASSERT("pbuf_header failed", err == ERR_OK); |
||||
} |
||||
|
||||
packet_idx = 0; |
||||
for (q = p; q != NULL; q = q->next) { |
||||
#if LWIPERF_CHECK_RX_DATA |
||||
const u8_t* payload = (const u8_t*)q->payload; |
||||
u16_t i; |
||||
for (i = 0; i < q->len; i++) { |
||||
u8_t val = payload[i]; |
||||
u8_t num = val - '0'; |
||||
if (num == conn->next_num) { |
||||
conn->next_num++; |
||||
if (conn->next_num == 10) { |
||||
conn->next_num = 0; |
||||
} |
||||
} else { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); |
||||
pbuf_free(p); |
||||
return ERR_VAL; |
||||
} |
||||
} |
||||
packet_idx += i; |
||||
#else |
||||
packet_idx += q->len; |
||||
#endif |
||||
} |
||||
LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); |
||||
conn->bytes_transferred += packet_idx; |
||||
tcp_recved(tpcb, tot_len); |
||||
pbuf_free(p); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/** Error callback, iperf tcp session aborted */ |
||||
static void |
||||
lwiperf_tcp_err(void *arg, err_t err) |
||||
{ |
||||
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; |
||||
LWIP_UNUSED_ARG(err); |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); |
||||
} |
||||
|
||||
/** TCP poll callback, try to send more data */ |
||||
static err_t |
||||
lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) |
||||
{ |
||||
lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; |
||||
LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); |
||||
LWIP_UNUSED_ARG(tpcb); |
||||
if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { |
||||
lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); |
||||
return ERR_OK; /* lwiperf_tcp_close frees conn */ |
||||
} |
||||
|
||||
if (!conn->base.server) { |
||||
lwiperf_tcp_client_send_more(conn); |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/** This is called when a new client connects for an iperf tcp session */ |
||||
static err_t |
||||
lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) |
||||
{ |
||||
lwiperf_state_tcp_t *s, *conn; |
||||
if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { |
||||
return ERR_VAL; |
||||
} |
||||
|
||||
s = (lwiperf_state_tcp_t*)arg; |
||||
conn = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); |
||||
if (conn == NULL) { |
||||
return ERR_MEM; |
||||
} |
||||
memset(conn, 0, sizeof(lwiperf_state_tcp_t)); |
||||
conn->base.tcp = 1; |
||||
conn->base.server = 1; |
||||
conn->base.related_server_state = &s->base; |
||||
conn->server_pcb = s->server_pcb; |
||||
conn->conn_pcb = newpcb; |
||||
conn->time_started = sys_now(); |
||||
conn->report_fn = s->report_fn; |
||||
conn->report_arg = s->report_arg; |
||||
|
||||
/* setup the tcp rx connection */ |
||||
tcp_arg(newpcb, conn); |
||||
tcp_recv(newpcb, lwiperf_tcp_recv); |
||||
tcp_poll(newpcb, lwiperf_tcp_poll, 2U); |
||||
tcp_err(conn->conn_pcb, lwiperf_tcp_err); |
||||
|
||||
lwiperf_list_add(&conn->base); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup iperf |
||||
* Start a TCP iperf server on the default TCP port (5001) and listen for |
||||
* incoming connections from iperf clients. |
||||
* |
||||
* @returns a connection handle that can be used to abort the server |
||||
* by calling @ref lwiperf_abort() |
||||
*/ |
||||
void* |
||||
lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg) |
||||
{ |
||||
return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, |
||||
report_fn, report_arg); |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup iperf |
||||
* Start a TCP iperf server on a specific IP address and port and listen for |
||||
* incoming connections from iperf clients. |
||||
* |
||||
* @returns a connection handle that can be used to abort the server |
||||
* by calling @ref lwiperf_abort() |
||||
*/ |
||||
void* |
||||
lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, |
||||
lwiperf_report_fn report_fn, void* report_arg) |
||||
{ |
||||
err_t err; |
||||
struct tcp_pcb* pcb; |
||||
lwiperf_state_tcp_t* s; |
||||
|
||||
if (local_addr == NULL) { |
||||
return NULL; |
||||
} |
||||
|
||||
s = (lwiperf_state_tcp_t*)LWIPERF_ALLOC(lwiperf_state_tcp_t); |
||||
if (s == NULL) { |
||||
return NULL; |
||||
} |
||||
memset(s, 0, sizeof(lwiperf_state_tcp_t)); |
||||
s->base.tcp = 1; |
||||
s->base.server = 1; |
||||
s->report_fn = report_fn; |
||||
s->report_arg = report_arg; |
||||
|
||||
pcb = tcp_new(); |
||||
if (pcb != NULL) { |
||||
err = tcp_bind(pcb, local_addr, local_port); |
||||
if (err == ERR_OK) { |
||||
s->server_pcb = tcp_listen_with_backlog(pcb, 1); |
||||
} |
||||
} |
||||
if (s->server_pcb == NULL) { |
||||
if (pcb != NULL) { |
||||
tcp_close(pcb); |
||||
} |
||||
LWIPERF_FREE(lwiperf_state_tcp_t, s); |
||||
return NULL; |
||||
} |
||||
pcb = NULL; |
||||
|
||||
tcp_arg(s->server_pcb, s); |
||||
tcp_accept(s->server_pcb, lwiperf_tcp_accept); |
||||
|
||||
lwiperf_list_add(&s->base); |
||||
return s; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup iperf |
||||
* Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) |
||||
*/ |
||||
void |
||||
lwiperf_abort(void* lwiperf_session) |
||||
{ |
||||
lwiperf_state_base_t* i, *dealloc, *last = NULL; |
||||
|
||||
for (i = lwiperf_all_connections; i != NULL; ) { |
||||
if ((i == lwiperf_session) || (i->related_server_state == lwiperf_session)) { |
||||
dealloc = i; |
||||
i = i->next; |
||||
if (last != NULL) { |
||||
last->next = i; |
||||
} |
||||
LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ |
||||
} else { |
||||
last = i; |
||||
i = i->next; |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endif /* LWIP_IPV4 && LWIP_TCP */ |
||||
@ -1,366 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* NetBIOS name service responder |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup netbiosns NETBIOS responder |
||||
* @ingroup apps |
||||
* |
||||
* This is an example implementation of a NetBIOS name server. |
||||
* It responds to name queries for a configurable name. |
||||
* Name resolving is not supported. |
||||
* |
||||
* Note that the device doesn't broadcast it's own name so can't |
||||
* detect duplicate names! |
||||
*/ |
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/netbiosns.h" |
||||
|
||||
#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "lwip/udp.h" |
||||
#include "lwip/netif.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
/** default port number for "NetBIOS Name service */ |
||||
#define NETBIOS_PORT 137 |
||||
|
||||
/** size of a NetBIOS name */ |
||||
#define NETBIOS_NAME_LEN 16 |
||||
|
||||
/** The Time-To-Live for NetBIOS name responds (in seconds)
|
||||
* Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ |
||||
#define NETBIOS_NAME_TTL 300000u |
||||
|
||||
/** NetBIOS header flags */ |
||||
#define NETB_HFLAG_RESPONSE 0x8000U |
||||
#define NETB_HFLAG_OPCODE 0x7800U |
||||
#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U |
||||
#define NETB_HFLAG_AUTHORATIVE 0x0400U |
||||
#define NETB_HFLAG_TRUNCATED 0x0200U |
||||
#define NETB_HFLAG_RECURS_DESIRED 0x0100U |
||||
#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U |
||||
#define NETB_HFLAG_BROADCAST 0x0010U |
||||
#define NETB_HFLAG_REPLYCODE 0x0008U |
||||
#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U |
||||
|
||||
/** NetBIOS name flags */ |
||||
#define NETB_NFLAG_UNIQUE 0x8000U |
||||
#define NETB_NFLAG_NODETYPE 0x6000U |
||||
#define NETB_NFLAG_NODETYPE_HNODE 0x6000U |
||||
#define NETB_NFLAG_NODETYPE_MNODE 0x4000U |
||||
#define NETB_NFLAG_NODETYPE_PNODE 0x2000U |
||||
#define NETB_NFLAG_NODETYPE_BNODE 0x0000U |
||||
|
||||
/** NetBIOS message header */ |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/bpstruct.h" |
||||
#endif |
||||
PACK_STRUCT_BEGIN |
||||
struct netbios_hdr { |
||||
PACK_STRUCT_FIELD(u16_t trans_id); |
||||
PACK_STRUCT_FIELD(u16_t flags); |
||||
PACK_STRUCT_FIELD(u16_t questions); |
||||
PACK_STRUCT_FIELD(u16_t answerRRs); |
||||
PACK_STRUCT_FIELD(u16_t authorityRRs); |
||||
PACK_STRUCT_FIELD(u16_t additionalRRs); |
||||
} PACK_STRUCT_STRUCT; |
||||
PACK_STRUCT_END |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/epstruct.h" |
||||
#endif |
||||
|
||||
/** NetBIOS message name part */ |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/bpstruct.h" |
||||
#endif |
||||
PACK_STRUCT_BEGIN |
||||
struct netbios_name_hdr { |
||||
PACK_STRUCT_FLD_8(u8_t nametype); |
||||
PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN*2)+1]); |
||||
PACK_STRUCT_FIELD(u16_t type); |
||||
PACK_STRUCT_FIELD(u16_t cls); |
||||
PACK_STRUCT_FIELD(u32_t ttl); |
||||
PACK_STRUCT_FIELD(u16_t datalen); |
||||
PACK_STRUCT_FIELD(u16_t flags); |
||||
PACK_STRUCT_FLD_S(ip4_addr_p_t addr); |
||||
} PACK_STRUCT_STRUCT; |
||||
PACK_STRUCT_END |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/epstruct.h" |
||||
#endif |
||||
|
||||
/** NetBIOS message */ |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/bpstruct.h" |
||||
#endif |
||||
PACK_STRUCT_BEGIN |
||||
struct netbios_resp |
||||
{ |
||||
struct netbios_hdr resp_hdr; |
||||
struct netbios_name_hdr resp_name; |
||||
} PACK_STRUCT_STRUCT; |
||||
PACK_STRUCT_END |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/epstruct.h" |
||||
#endif |
||||
|
||||
#ifdef NETBIOS_LWIP_NAME |
||||
#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME |
||||
#else |
||||
static char netbiosns_local_name[NETBIOS_NAME_LEN]; |
||||
#define NETBIOS_LOCAL_NAME netbiosns_local_name |
||||
#endif |
||||
|
||||
struct udp_pcb *netbiosns_pcb; |
||||
|
||||
/** Decode a NetBIOS name (from packet to string) */ |
||||
static int |
||||
netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) |
||||
{ |
||||
char *pname; |
||||
char cname; |
||||
char cnbname; |
||||
int idx = 0; |
||||
|
||||
LWIP_UNUSED_ARG(name_dec_len); |
||||
|
||||
/* Start decoding netbios name. */ |
||||
pname = name_enc; |
||||
for (;;) { |
||||
/* Every two characters of the first level-encoded name
|
||||
* turn into one character in the decoded name. */ |
||||
cname = *pname; |
||||
if (cname == '\0') |
||||
break; /* no more characters */ |
||||
if (cname == '.') |
||||
break; /* scope ID follows */ |
||||
if (cname < 'A' || cname > 'Z') { |
||||
/* Not legal. */ |
||||
return -1; |
||||
} |
||||
cname -= 'A'; |
||||
cnbname = cname << 4; |
||||
pname++; |
||||
|
||||
cname = *pname; |
||||
if (cname == '\0' || cname == '.') { |
||||
/* No more characters in the name - but we're in
|
||||
* the middle of a pair. Not legal. */ |
||||
return -1; |
||||
} |
||||
if (cname < 'A' || cname > 'Z') { |
||||
/* Not legal. */ |
||||
return -1; |
||||
} |
||||
cname -= 'A'; |
||||
cnbname |= cname; |
||||
pname++; |
||||
|
||||
/* Do we have room to store the character? */ |
||||
if (idx < NETBIOS_NAME_LEN) { |
||||
/* Yes - store the character. */ |
||||
name_dec[idx++] = (cnbname!=' '?cnbname:'\0'); |
||||
} |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#if 0 /* function currently unused */
|
||||
/** Encode a NetBIOS name (from string to packet) - currently unused because
|
||||
we don't ask for names. */ |
||||
static int |
||||
netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) |
||||
{ |
||||
char *pname; |
||||
char cname; |
||||
unsigned char ucname; |
||||
int idx = 0; |
||||
|
||||
/* Start encoding netbios name. */ |
||||
pname = name_enc; |
||||
|
||||
for (;;) { |
||||
/* Every two characters of the first level-encoded name
|
||||
* turn into one character in the decoded name. */ |
||||
cname = *pname; |
||||
if (cname == '\0') |
||||
break; /* no more characters */ |
||||
if (cname == '.') |
||||
break; /* scope ID follows */ |
||||
if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { |
||||
/* Not legal. */ |
||||
return -1; |
||||
} |
||||
|
||||
/* Do we have room to store the character? */ |
||||
if (idx >= name_dec_len) { |
||||
return -1; |
||||
} |
||||
|
||||
/* Yes - store the character. */ |
||||
ucname = cname; |
||||
name_dec[idx++] = ('A'+((ucname>>4) & 0x0F)); |
||||
name_dec[idx++] = ('A'+( ucname & 0x0F)); |
||||
pname++; |
||||
} |
||||
|
||||
/* Fill with "space" coding */ |
||||
for (;idx < name_dec_len - 1;) { |
||||
name_dec[idx++] = 'C'; |
||||
name_dec[idx++] = 'A'; |
||||
} |
||||
|
||||
/* Terminate string */ |
||||
name_dec[idx] = '\0'; |
||||
|
||||
return 0; |
||||
} |
||||
#endif /* 0 */ |
||||
|
||||
/** NetBIOS Name service recv callback */ |
||||
static void |
||||
netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) |
||||
{ |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
/* if packet is valid */ |
||||
if (p != NULL) { |
||||
char netbios_name[NETBIOS_NAME_LEN+1]; |
||||
struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload; |
||||
struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1); |
||||
|
||||
/* we only answer if we got a default interface */ |
||||
if (netif_default != NULL) { |
||||
/* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ |
||||
/* if the packet is a NetBIOS name query question */ |
||||
if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && |
||||
((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && |
||||
(netbios_hdr->questions == PP_NTOHS(1))) { |
||||
/* decode the NetBIOS name */ |
||||
netbiosns_name_decode((char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name)); |
||||
/* if the packet is for us */ |
||||
if (NETBIOS_STRCMP(netbios_name, NETBIOS_LOCAL_NAME) == 0) { |
||||
struct pbuf *q; |
||||
struct netbios_resp *resp; |
||||
|
||||
q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); |
||||
if (q != NULL) { |
||||
resp = (struct netbios_resp*)q->payload; |
||||
|
||||
/* prepare NetBIOS header response */ |
||||
resp->resp_hdr.trans_id = netbios_hdr->trans_id; |
||||
resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | |
||||
NETB_HFLAG_OPCODE_NAME_QUERY | |
||||
NETB_HFLAG_AUTHORATIVE | |
||||
NETB_HFLAG_RECURS_DESIRED); |
||||
resp->resp_hdr.questions = 0; |
||||
resp->resp_hdr.answerRRs = PP_HTONS(1); |
||||
resp->resp_hdr.authorityRRs = 0; |
||||
resp->resp_hdr.additionalRRs = 0; |
||||
|
||||
/* prepare NetBIOS header datas */ |
||||
MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname)); |
||||
resp->resp_name.nametype = netbios_name_hdr->nametype; |
||||
resp->resp_name.type = netbios_name_hdr->type; |
||||
resp->resp_name.cls = netbios_name_hdr->cls; |
||||
resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); |
||||
resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr)); |
||||
resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); |
||||
ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); |
||||
|
||||
/* send the NetBIOS response */ |
||||
udp_sendto(upcb, q, addr, port); |
||||
|
||||
/* free the "reference" pbuf */ |
||||
pbuf_free(q); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
/* free the pbuf */ |
||||
pbuf_free(p); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup netbiosns
|
||||
* Init netbios responder |
||||
*/ |
||||
void |
||||
netbiosns_init(void) |
||||
{ |
||||
#ifdef NETBIOS_LWIP_NAME |
||||
LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); |
||||
#endif |
||||
|
||||
netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); |
||||
if (netbiosns_pcb != NULL) { |
||||
/* we have to be allowed to send broadcast packets! */ |
||||
netbiosns_pcb->so_options |= SOF_BROADCAST; |
||||
udp_bind(netbiosns_pcb, IP_ANY_TYPE, NETBIOS_PORT); |
||||
udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); |
||||
} |
||||
} |
||||
|
||||
#ifndef NETBIOS_LWIP_NAME |
||||
/**
|
||||
* @ingroup netbiosns
|
||||
* Set netbios name. ATTENTION: the hostname must be less than 15 characters! |
||||
*/ |
||||
void |
||||
netbiosns_set_name(const char* hostname) |
||||
{ |
||||
size_t copy_len = strlen(hostname); |
||||
LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); |
||||
if (copy_len >= NETBIOS_NAME_LEN) { |
||||
copy_len = NETBIOS_NAME_LEN - 1; |
||||
} |
||||
memcpy(netbiosns_local_name, hostname, copy_len + 1); |
||||
} |
||||
#endif |
||||
|
||||
/**
|
||||
* @ingroup netbiosns
|
||||
* Stop netbios responder |
||||
*/ |
||||
void |
||||
netbiosns_stop(void) |
||||
{ |
||||
if (netbiosns_pcb != NULL) { |
||||
udp_remove(netbiosns_pcb); |
||||
netbiosns_pcb = NULL; |
||||
} |
||||
} |
||||
|
||||
#endif /* LWIP_IPV4 && LWIP_UDP */ |
||||
@ -1,38 +0,0 @@
|
||||
lwIP SNMPv2c agent |
||||
================== |
||||
|
||||
Based on SNMP stack written by Christiaan Simons <christiaan.simons@axon.tv> |
||||
|
||||
Rewritten by Martin Hentschel <info@cl-soft.de> and |
||||
Dirk Ziegelmeier <dziegel@gmx.de> |
||||
|
||||
Features: |
||||
- SNMPv2c support. |
||||
- Low RAM usage - no memory pools, stack only. |
||||
- MIB2 implementation is separated from SNMP stack. |
||||
- Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. |
||||
- Simple and generic API for MIB implementation. |
||||
- Comfortable node types and helper functions for scalar arrays and tables. |
||||
- Counter64, bit and truthvalue datatype support. |
||||
- Callbacks for SNMP writes e.g. to implement persistency. |
||||
- Runs on two APIs: RAW and netconn. |
||||
- Async API is gone - the stack now supports netconn API instead, |
||||
so blocking operations can be done in MIB calls. |
||||
SNMP runs in a worker thread when netconn API is used. |
||||
- Simplified thread sync support for MIBs - useful when MIBs |
||||
need to access variables shared with other threads where no locking is |
||||
possible. Used in MIB2 to access lwIP stats from lwIP thread. |
||||
|
||||
MIB compiler (code generator): |
||||
- Written in C#. MIB viewer used Windows Forms. |
||||
- Developed on Windows with Visual Studio 2010. |
||||
- Can be compiled and used under Linux with http://www.monodevelop.com/. |
||||
- Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) |
||||
(https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). |
||||
- MIB parser, C file generation framework and LWIP code generation are cleanly |
||||
separated, which means the code may be useful as a base for code generation |
||||
of other SNMP agents. |
||||
|
||||
Notes: |
||||
- Stack and MIB compiler were used to implement a Profinet device. |
||||
Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. |
||||
@ -1,749 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Abstract Syntax Notation One (ISO 8824, 8825) encoding |
||||
* |
||||
* @todo not optimised (yet), favor correctness over speed, favor speed over size |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv> |
||||
* Martin Hentschel <info@cl-soft.de> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "snmp_asn1.h" |
||||
|
||||
#define PBUF_OP_EXEC(code) \ |
||||
if ((code) != ERR_OK) { \
|
||||
return ERR_BUF; \
|
||||
} |
||||
|
||||
/**
|
||||
* Encodes a TLV into a pbuf stream. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param tlv TLV to encode |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
*/ |
||||
err_t |
||||
snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) |
||||
{ |
||||
u8_t data; |
||||
u8_t length_bytes_required; |
||||
|
||||
/* write type */ |
||||
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { |
||||
/* extended format is not used by SNMP so we do not accept those values */ |
||||
return ERR_ARG; |
||||
} |
||||
if (tlv->type_len != 0) { |
||||
/* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); |
||||
tlv->type_len = 1; |
||||
|
||||
/* write length */ |
||||
if (tlv->value_len <= 127) { |
||||
length_bytes_required = 1; |
||||
} else if (tlv->value_len <= 255) { |
||||
length_bytes_required = 2; |
||||
} else { |
||||
length_bytes_required = 3; |
||||
} |
||||
|
||||
/* check for forced min length */ |
||||
if (tlv->length_len > 0) { |
||||
if (tlv->length_len < length_bytes_required) { |
||||
/* unable to code requested length in requested number of bytes */ |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
length_bytes_required = tlv->length_len; |
||||
} else { |
||||
tlv->length_len = length_bytes_required; |
||||
} |
||||
|
||||
if (length_bytes_required > 1) { |
||||
/* multi byte representation required */ |
||||
length_bytes_required--; |
||||
data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ |
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); |
||||
|
||||
while (length_bytes_required > 1) { |
||||
if (length_bytes_required == 2) { |
||||
/* append high byte */ |
||||
data = (u8_t)(tlv->value_len >> 8); |
||||
} else { |
||||
/* append leading 0x00 */ |
||||
data = 0x00; |
||||
} |
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); |
||||
length_bytes_required--; |
||||
} |
||||
} |
||||
|
||||
/* append low byte */ |
||||
data = (u8_t)(tlv->value_len & 0xFF); |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param raw_len raw data length |
||||
* @param raw points raw data |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
*/ |
||||
err_t |
||||
snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len) |
||||
{ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) |
||||
* @param value is the host order u32_t value to be encoded |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
* |
||||
* @see snmp_asn1_enc_u32t_cnt() |
||||
*/ |
||||
err_t |
||||
snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value) |
||||
{ |
||||
if (octets_needed > 5) { |
||||
return ERR_ARG; |
||||
} |
||||
if (octets_needed == 5) { |
||||
/* not enough bits in 'value' add leading 0x00 */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); |
||||
octets_needed--; |
||||
} |
||||
|
||||
while (octets_needed > 1) { |
||||
octets_needed--; |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); |
||||
} |
||||
|
||||
/* (only) one least significant octet */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Encodes u64_t (counter64) into a pbuf chained ASN1 msg. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) |
||||
* @param value is the host order u32_t value to be encoded |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
* |
||||
* @see snmp_asn1_enc_u64t_cnt() |
||||
*/ |
||||
err_t |
||||
snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value) |
||||
{ |
||||
if (octets_needed > 9) { |
||||
return ERR_ARG; |
||||
} |
||||
if (octets_needed == 9) { |
||||
/* not enough bits in 'value' add leading 0x00 */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); |
||||
octets_needed--; |
||||
} |
||||
|
||||
while (octets_needed > 4) { |
||||
octets_needed--; |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> ((octets_needed-4) << 3)))); |
||||
} |
||||
|
||||
/* skip to low u32 */ |
||||
value++; |
||||
|
||||
while (octets_needed > 1) { |
||||
octets_needed--; |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value >> (octets_needed << 3)))); |
||||
} |
||||
|
||||
/* always write at least one octet (also in case of value == 0) */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(*value))); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Encodes s32_t integer into a pbuf chained ASN1 msg. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) |
||||
* @param value is the host order s32_t value to be encoded |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
* |
||||
* @see snmp_asn1_enc_s32t_cnt() |
||||
*/ |
||||
err_t |
||||
snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value) |
||||
{ |
||||
while (octets_needed > 1) { |
||||
octets_needed--; |
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); |
||||
} |
||||
|
||||
/* (only) one least significant octet */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Encodes object identifier into a pbuf chained ASN1 msg. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param oid points to object identifier array |
||||
* @param oid_len object identifier array length |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode |
||||
*/ |
||||
err_t |
||||
snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len) |
||||
{ |
||||
if (oid_len > 1) { |
||||
/* write compressed first two sub id's */ |
||||
u32_t compressed_byte = ((oid[0] * 40) + oid[1]); |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); |
||||
oid_len -= 2; |
||||
oid += 2; |
||||
} else { |
||||
/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ |
||||
/* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
while (oid_len > 0) { |
||||
u32_t sub_id; |
||||
u8_t shift, tail; |
||||
|
||||
oid_len--; |
||||
sub_id = *oid; |
||||
tail = 0; |
||||
shift = 28; |
||||
while (shift > 0) { |
||||
u8_t code; |
||||
|
||||
code = (u8_t)(sub_id >> shift); |
||||
if ((code != 0) || (tail != 0)) { |
||||
tail = 1; |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); |
||||
} |
||||
shift -= 7; |
||||
} |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); |
||||
|
||||
/* proceed to next sub-identifier */ |
||||
oid++; |
||||
} |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Returns octet count for length. |
||||
* |
||||
* @param length |
||||
* @param octets_needed points to the return value |
||||
*/ |
||||
void |
||||
snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) |
||||
{ |
||||
if (length < 0x80U) { |
||||
*octets_needed = 1; |
||||
} else if (length < 0x100U) { |
||||
*octets_needed = 2; |
||||
} else { |
||||
*octets_needed = 3; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns octet count for an u32_t. |
||||
* |
||||
* @param value |
||||
* @param octets_needed points to the return value |
||||
* |
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded |
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value |
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! |
||||
*/ |
||||
void |
||||
snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) |
||||
{ |
||||
if (value < 0x80UL) { |
||||
*octets_needed = 1; |
||||
} else if (value < 0x8000UL) { |
||||
*octets_needed = 2; |
||||
} else if (value < 0x800000UL) { |
||||
*octets_needed = 3; |
||||
} else if (value < 0x80000000UL) { |
||||
*octets_needed = 4; |
||||
} else { |
||||
*octets_needed = 5; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns octet count for an u64_t. |
||||
* |
||||
* @param value |
||||
* @param octets_needed points to the return value |
||||
* |
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded |
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value |
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! |
||||
*/ |
||||
void |
||||
snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed) |
||||
{ |
||||
/* check if high u32 is 0 */ |
||||
if (*value == 0x00) { |
||||
/* only low u32 is important */ |
||||
value++; |
||||
snmp_asn1_enc_u32t_cnt(*value, octets_needed); |
||||
} else { |
||||
/* low u32 does not matter for length determination */ |
||||
snmp_asn1_enc_u32t_cnt(*value, octets_needed); |
||||
*octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns octet count for an s32_t. |
||||
* |
||||
* @param value |
||||
* @param octets_needed points to the return value |
||||
* |
||||
* @note ASN coded integers are _always_ signed. |
||||
*/ |
||||
void |
||||
snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) |
||||
{ |
||||
if (value < 0) { |
||||
value = ~value; |
||||
}
|
||||
if (value < 0x80L) { |
||||
*octets_needed = 1; |
||||
} else if (value < 0x8000L) { |
||||
*octets_needed = 2; |
||||
} else if (value < 0x800000L) { |
||||
*octets_needed = 3; |
||||
} else { |
||||
*octets_needed = 4; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Returns octet count for an object identifier. |
||||
* |
||||
* @param oid points to object identifier array |
||||
* @param oid_len object identifier array length |
||||
* @param octets_needed points to the return value |
||||
*/ |
||||
void |
||||
snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) |
||||
{ |
||||
u32_t sub_id; |
||||
|
||||
*octets_needed = 0; |
||||
if (oid_len > 1) { |
||||
/* compressed prefix in one octet */ |
||||
(*octets_needed)++; |
||||
oid_len -= 2; |
||||
oid += 2; |
||||
} |
||||
while (oid_len > 0) { |
||||
oid_len--; |
||||
sub_id = *oid; |
||||
|
||||
sub_id >>= 7; |
||||
(*octets_needed)++; |
||||
while (sub_id > 0) { |
||||
sub_id >>= 7; |
||||
(*octets_needed)++; |
||||
} |
||||
oid++; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Decodes a TLV from a pbuf stream. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param tlv returns decoded TLV |
||||
* @return ERR_OK if successful, ERR_VAL if we can't decode |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv) |
||||
{ |
||||
u8_t data; |
||||
|
||||
/* decode type first */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
tlv->type = data; |
||||
|
||||
if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { |
||||
/* extended format is not used by SNMP so we do not accept those values */ |
||||
return ERR_VAL; |
||||
} |
||||
tlv->type_len = 1; |
||||
|
||||
/* now, decode length */ |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
|
||||
if (data < 0x80) { /* short form */ |
||||
tlv->length_len = 1; |
||||
tlv->value_len = data; |
||||
} else if (data > 0x80) { /* long form */ |
||||
u8_t length_bytes = data - 0x80; |
||||
tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ |
||||
tlv->value_len = 0; |
||||
|
||||
while (length_bytes > 0) { |
||||
/* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ |
||||
if (tlv->value_len > 0xFF) { |
||||
return ERR_VAL; |
||||
} |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
tlv->value_len <<= 8; |
||||
tlv->value_len |= data; |
||||
|
||||
/* take care for special value used for indefinite length */ |
||||
if (tlv->value_len == 0xFFFF) { |
||||
return ERR_VAL; |
||||
} |
||||
|
||||
length_bytes--; |
||||
} |
||||
} else { /* data == 0x80 indefinite length form */ |
||||
/* (not allowed for SNMP; RFC 1157, 3.2.2) */ |
||||
return ERR_VAL; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Decodes positive integer (counter, gauge, timeticks) into u32_t. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param len length of the coded integer field |
||||
* @param value return host order integer |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode |
||||
* |
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded |
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value |
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) |
||||
{ |
||||
u8_t data; |
||||
|
||||
if ((len > 0) && (len <= 5)) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
|
||||
/* expecting sign bit to be zero, only unsigned please! */ |
||||
if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { |
||||
*value = data; |
||||
len--; |
||||
|
||||
while (len > 0) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
*value <<= 8; |
||||
*value |= data; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
} |
||||
|
||||
return ERR_VAL; |
||||
} |
||||
|
||||
/**
|
||||
* Decodes large positive integer (counter64) into 2x u32_t. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param len length of the coded integer field |
||||
* @param value return host order integer |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode |
||||
* |
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded |
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value |
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) |
||||
{ |
||||
u8_t data; |
||||
|
||||
if (len <= 4) { |
||||
/* high u32 is 0 */ |
||||
*value = 0; |
||||
/* directly skip to low u32 */ |
||||
value++; |
||||
} |
||||
|
||||
if ((len > 0) && (len <= 9)) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
|
||||
/* expecting sign bit to be zero, only unsigned please! */ |
||||
if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { |
||||
*value = data; |
||||
len--; |
||||
|
||||
while (len > 0) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
|
||||
if (len == 4) { |
||||
/* skip to low u32 */ |
||||
value++; |
||||
*value = 0; |
||||
} else { |
||||
*value <<= 8; |
||||
} |
||||
|
||||
*value |= data; |
||||
len--; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
} |
||||
|
||||
return ERR_VAL; |
||||
} |
||||
|
||||
/**
|
||||
* Decodes integer into s32_t. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param len length of the coded integer field |
||||
* @param value return host order integer |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode |
||||
* |
||||
* @note ASN coded integers are _always_ signed! |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) |
||||
{ |
||||
#if BYTE_ORDER == LITTLE_ENDIAN |
||||
u8_t *lsb_ptr = (u8_t*)value; |
||||
#endif |
||||
#if BYTE_ORDER == BIG_ENDIAN |
||||
u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1; |
||||
#endif |
||||
u8_t sign; |
||||
u8_t data; |
||||
|
||||
if ((len > 0) && (len < 5)) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
if (data & 0x80) { |
||||
/* negative, start from -1 */ |
||||
*value = -1; |
||||
sign = 1; |
||||
*lsb_ptr &= data; |
||||
} else { |
||||
/* positive, start from 0 */ |
||||
*value = 0; |
||||
sign = 0; |
||||
*lsb_ptr |= data; |
||||
} |
||||
|
||||
/* OR/AND octets with value */ |
||||
while (len > 0) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN |
||||
*value <<= 8; |
||||
#endif |
||||
#if BYTE_ORDER == BIG_ENDIAN |
||||
*value >>= 8; |
||||
#endif |
||||
|
||||
if (sign) { |
||||
*lsb_ptr |= 255; |
||||
*lsb_ptr &= data; |
||||
} else { |
||||
*lsb_ptr |= data; |
||||
} |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
return ERR_VAL; |
||||
} |
||||
|
||||
/**
|
||||
* Decodes object identifier from incoming message into array of u32_t. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param len length of the coded object identifier |
||||
* @param oid return decoded object identifier |
||||
* @param oid_len return decoded object identifier length |
||||
* @param oid_max_len size of oid buffer |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len) |
||||
{ |
||||
u32_t *oid_ptr; |
||||
u8_t data; |
||||
|
||||
*oid_len = 0; |
||||
oid_ptr = oid; |
||||
if (len > 0) { |
||||
if (oid_max_len < 2) { |
||||
return ERR_MEM; |
||||
} |
||||
|
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
/* first compressed octet */ |
||||
if (data == 0x2B) { |
||||
/* (most) common case 1.3 (iso.org) */ |
||||
*oid_ptr = 1; |
||||
oid_ptr++; |
||||
*oid_ptr = 3; |
||||
oid_ptr++; |
||||
} else if (data < 40) { |
||||
*oid_ptr = 0; |
||||
oid_ptr++; |
||||
*oid_ptr = data; |
||||
oid_ptr++; |
||||
} else if (data < 80) { |
||||
*oid_ptr = 1; |
||||
oid_ptr++; |
||||
*oid_ptr = data - 40; |
||||
oid_ptr++; |
||||
} else { |
||||
*oid_ptr = 2; |
||||
oid_ptr++; |
||||
*oid_ptr = data - 80; |
||||
oid_ptr++; |
||||
} |
||||
*oid_len = 2; |
||||
} else { |
||||
/* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ |
||||
return ERR_OK; |
||||
} |
||||
|
||||
while ((len > 0) && (*oid_len < oid_max_len)) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
if ((data & 0x80) == 0x00) { |
||||
/* sub-identifier uses single octet */ |
||||
*oid_ptr = data; |
||||
} else { |
||||
/* sub-identifier uses multiple octets */ |
||||
u32_t sub_id = (data & ~0x80); |
||||
while ((len > 0) && ((data & 0x80) != 0)) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); |
||||
len--; |
||||
|
||||
sub_id = (sub_id << 7) + (data & ~0x80); |
||||
} |
||||
|
||||
if ((data & 0x80) != 0) { |
||||
/* "more bytes following" bit still set at end of len */ |
||||
return ERR_VAL; |
||||
} |
||||
*oid_ptr = sub_id; |
||||
} |
||||
oid_ptr++; |
||||
(*oid_len)++; |
||||
} |
||||
|
||||
if (len > 0) { |
||||
/* OID to long to fit in our buffer */ |
||||
return ERR_MEM; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) |
||||
* from incoming message into array. |
||||
* |
||||
* @param pbuf_stream points to a pbuf stream |
||||
* @param len length of the coded raw data (zero is valid, e.g. empty string!) |
||||
* @param buf return raw bytes |
||||
* @param buf_len returns length of the raw return value |
||||
* @param buf_max_len buffer size |
||||
* @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode |
||||
*/ |
||||
err_t |
||||
snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len) |
||||
{ |
||||
if (len > buf_max_len) { |
||||
/* not enough dst space */ |
||||
return ERR_MEM; |
||||
} |
||||
*buf_len = len; |
||||
|
||||
while (len > 0) { |
||||
PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); |
||||
buf++; |
||||
len--; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,108 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Abstract Syntax Notation One (ISO 8824, 8825) codec. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* Copyright (c) 2016 Elias Oenal. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv> |
||||
* Martin Hentschel <info@cl-soft.de> |
||||
* Elias Oenal <lwip@eliasoenal.com> |
||||
*/ |
||||
|
||||
#ifndef LWIP_HDR_APPS_SNMP_ASN1_H |
||||
#define LWIP_HDR_APPS_SNMP_ASN1_H |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP |
||||
|
||||
#include "lwip/err.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "snmp_pbuf_stream.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 |
||||
|
||||
#define SNMP_ASN1_CLASS_MASK 0xC0 |
||||
#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 |
||||
#define SNMP_ASN1_DATATYPE_MASK 0x1F |
||||
#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ |
||||
|
||||
/* context specific (SNMP) tags (from SNMP spec. RFC1157) */ |
||||
#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 |
||||
#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 |
||||
#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 |
||||
#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 |
||||
#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 |
||||
#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 |
||||
|
||||
#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 |
||||
#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 |
||||
|
||||
struct snmp_asn1_tlv |
||||
{ |
||||
u8_t type; /* only U8 because extended types are not specified by SNMP */ |
||||
u8_t type_len; /* encoded length of 'type' field (normally 1) */ |
||||
u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ |
||||
u16_t value_len; /* encoded length of the value */ |
||||
}; |
||||
#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) |
||||
#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) |
||||
#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); |
||||
|
||||
err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); |
||||
err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); |
||||
err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); |
||||
err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); |
||||
err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t* oid, u8_t* oid_len, u8_t oid_max_len); |
||||
err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t* buf_len, u16_t buf_max_len); |
||||
|
||||
err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream* pbuf_stream, struct snmp_asn1_tlv* tlv); |
||||
|
||||
void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); |
||||
void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); |
||||
void snmp_asn1_enc_u64t_cnt(const u32_t *value, u16_t *octets_needed); |
||||
void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); |
||||
void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); |
||||
err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream* pbuf_stream, const u32_t *oid, u16_t oid_len); |
||||
err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, s32_t value); |
||||
err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, u32_t value); |
||||
err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream* pbuf_stream, u16_t octets_needed, const u32_t* value); |
||||
err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream* pbuf_stream, const u8_t *raw, u16_t raw_len); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
|
||||
#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ |
||||
File diff suppressed because it is too large
Load Diff
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel <info@cl-soft.de> |
||||
* |
||||
*/ |
||||
|
||||
#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H |
||||
#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "snmp_asn1.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* (outdated) SNMPv1 error codes
|
||||
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request |
||||
*/ |
||||
#define SNMP_ERR_NOSUCHNAME 2 |
||||
#define SNMP_ERR_BADVALUE 3 |
||||
#define SNMP_ERR_READONLY 4 |
||||
/* error codes which are internal and shall not be used by MIBS
|
||||
* shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request |
||||
*/ |
||||
#define SNMP_ERR_TOOBIG 1 |
||||
#define SNMP_ERR_AUTHORIZATIONERROR 16 |
||||
#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT |
||||
#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW |
||||
|
||||
|
||||
const struct snmp_node* snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t* oid_instance_len); |
||||
const struct snmp_node* snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id* oidret); |
||||
|
||||
typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance*, void*); |
||||
|
||||
u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance* node_instance); |
||||
u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void* validate_node_instance_arg, struct snmp_obj_id* node_oid, struct snmp_node_instance* node_instance); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
|
||||
#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ |
||||
@ -1,116 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup snmp_mib2 MIB2 |
||||
* @ingroup snmp |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#if !LWIP_STATS |
||||
#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) |
||||
#endif |
||||
#if !MIB2_STATS |
||||
#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) |
||||
#endif |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#include "lwip/tcpip.h" |
||||
#include "lwip/priv/tcpip_priv.h" |
||||
void |
||||
snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg) |
||||
{ |
||||
#if LWIP_TCPIP_CORE_LOCKING |
||||
LOCK_TCPIP_CORE(); |
||||
fn(arg); |
||||
UNLOCK_TCPIP_CORE(); |
||||
#else |
||||
tcpip_callback(fn, arg); |
||||
#endif |
||||
} |
||||
|
||||
struct snmp_threadsync_instance snmp_mib2_lwip_locks; |
||||
#endif |
||||
|
||||
/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ |
||||
/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ |
||||
/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ |
||||
|
||||
/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ |
||||
extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; |
||||
extern const struct snmp_tree_node snmp_mib2_udp_root; |
||||
extern const struct snmp_tree_node snmp_mib2_tcp_root; |
||||
extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; |
||||
extern const struct snmp_tree_node snmp_mib2_interface_root; |
||||
extern const struct snmp_scalar_array_node snmp_mib2_system_node; |
||||
extern const struct snmp_tree_node snmp_mib2_at_root; |
||||
extern const struct snmp_tree_node snmp_mib2_ip_root; |
||||
|
||||
static const struct snmp_node* const mib2_nodes[] = { |
||||
&snmp_mib2_system_node.node.node, |
||||
&snmp_mib2_interface_root.node, |
||||
#if LWIP_ARP && LWIP_IPV4 |
||||
&snmp_mib2_at_root.node, |
||||
#endif /* LWIP_ARP && LWIP_IPV4 */ |
||||
#if LWIP_IPV4 |
||||
&snmp_mib2_ip_root.node, |
||||
#endif /* LWIP_IPV4 */ |
||||
#if LWIP_ICMP |
||||
&snmp_mib2_icmp_root.node.node, |
||||
#endif /* LWIP_ICMP */ |
||||
#if LWIP_TCP |
||||
&snmp_mib2_tcp_root.node, |
||||
#endif /* LWIP_TCP */ |
||||
#if LWIP_UDP |
||||
&snmp_mib2_udp_root.node, |
||||
#endif /* LWIP_UDP */ |
||||
&snmp_mib2_snmp_root.node.node |
||||
}; |
||||
|
||||
static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); |
||||
|
||||
static const u32_t mib2_base_oid_arr[] = { 1,3,6,1,2,1 }; |
||||
const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ |
||||
@ -1,182 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) ICMP objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/icmp.h" |
||||
#include "lwip/stats.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ |
||||
|
||||
static s16_t |
||||
icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) |
||||
{ |
||||
u32_t *uint_ptr = (u32_t*)value; |
||||
|
||||
switch (node->oid) { |
||||
case 1: /* icmpInMsgs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinmsgs); |
||||
return sizeof(*uint_ptr); |
||||
case 2: /* icmpInErrors */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinerrors); |
||||
return sizeof(*uint_ptr); |
||||
case 3: /* icmpInDestUnreachs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpindestunreachs); |
||||
return sizeof(*uint_ptr); |
||||
case 4: /* icmpInTimeExcds */ |
||||
*uint_ptr = STATS_GET(mib2.icmpintimeexcds); |
||||
return sizeof(*uint_ptr); |
||||
case 5: /* icmpInParmProbs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinparmprobs); |
||||
return sizeof(*uint_ptr); |
||||
case 6: /* icmpInSrcQuenchs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); |
||||
return sizeof(*uint_ptr); |
||||
case 7: /* icmpInRedirects */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinredirects); |
||||
return sizeof(*uint_ptr); |
||||
case 8: /* icmpInEchos */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinechos); |
||||
return sizeof(*uint_ptr); |
||||
case 9: /* icmpInEchoReps */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinechoreps); |
||||
return sizeof(*uint_ptr); |
||||
case 10: /* icmpInTimestamps */ |
||||
*uint_ptr = STATS_GET(mib2.icmpintimestamps); |
||||
return sizeof(*uint_ptr); |
||||
case 11: /* icmpInTimestampReps */ |
||||
*uint_ptr = STATS_GET(mib2.icmpintimestampreps); |
||||
return sizeof(*uint_ptr); |
||||
case 12: /* icmpInAddrMasks */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinaddrmasks); |
||||
return sizeof(*uint_ptr); |
||||
case 13: /* icmpInAddrMaskReps */ |
||||
*uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); |
||||
return sizeof(*uint_ptr); |
||||
case 14: /* icmpOutMsgs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpoutmsgs); |
||||
return sizeof(*uint_ptr); |
||||
case 15: /* icmpOutErrors */ |
||||
*uint_ptr = STATS_GET(mib2.icmpouterrors); |
||||
return sizeof(*uint_ptr); |
||||
case 16: /* icmpOutDestUnreachs */ |
||||
*uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); |
||||
return sizeof(*uint_ptr); |
||||
case 17: /* icmpOutTimeExcds */ |
||||
*uint_ptr = STATS_GET(mib2.icmpouttimeexcds); |
||||
return sizeof(*uint_ptr); |
||||
case 18: /* icmpOutParmProbs: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 20: /* icmpOutRedirects: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 21: /* icmpOutEchos */ |
||||
*uint_ptr = STATS_GET(mib2.icmpoutechos); |
||||
return sizeof(*uint_ptr); |
||||
case 22: /* icmpOutEchoReps */ |
||||
*uint_ptr = STATS_GET(mib2.icmpoutechoreps); |
||||
return sizeof(*uint_ptr); |
||||
case 23: /* icmpOutTimestamps: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 24: /* icmpOutTimestampReps: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 25: /* icmpOutAddrMasks: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); |
||||
break; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
static const struct snmp_scalar_array_node_def icmp_nodes[] = { |
||||
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, |
||||
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} |
||||
}; |
||||
|
||||
const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ |
||||
@ -1,376 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) INTERFACES objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/netif.h" |
||||
#include "lwip/stats.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
|
||||
/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ |
||||
|
||||
static s16_t
|
||||
interfaces_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
if (instance->node->oid == 1) { |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
s32_t num_netifs = 0; |
||||
|
||||
struct netif *netif = netif_list; |
||||
while (netif != NULL) { |
||||
num_netifs++; |
||||
netif = netif->next; |
||||
} |
||||
|
||||
*sint_ptr = num_netifs; |
||||
return sizeof(*sint_ptr); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { |
||||
{ 1, 0xff } /* netif->num is u8_t */ |
||||
}; |
||||
|
||||
static const u8_t iftable_ifOutQLen = 0; |
||||
|
||||
static const u8_t iftable_ifOperStatus_up = 1; |
||||
static const u8_t iftable_ifOperStatus_down = 2; |
||||
|
||||
static const u8_t iftable_ifAdminStatus_up = 1; |
||||
static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; |
||||
static const u8_t iftable_ifAdminStatus_down = 2; |
||||
|
||||
static snmp_err_t |
||||
interfaces_Table_get_cell_instance(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance) |
||||
{ |
||||
u32_t ifIndex; |
||||
struct netif *netif; |
||||
|
||||
LWIP_UNUSED_ARG(column); |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get netif index from incoming OID */ |
||||
ifIndex = row_oid[0]; |
||||
|
||||
/* find netif with index */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
if (netif_to_num(netif) == ifIndex) { |
||||
/* store netif pointer for subsequent operations (get/test/set) */ |
||||
cell_instance->reference.ptr = netif; |
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
interfaces_Table_get_next_cell_instance(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance) |
||||
{ |
||||
struct netif *netif; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; |
||||
|
||||
LWIP_UNUSED_ARG(column); |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; |
||||
test_oid[0] = netif_to_num(netif); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); |
||||
|
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* store netif pointer for subsequent operations (get/test/set) */ |
||||
cell_instance->reference.ptr = /* (struct netif*) */state.reference; |
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static s16_t |
||||
interfaces_Table_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
struct netif *netif = (struct netif*)instance->reference.ptr; |
||||
u32_t* value_u32 = (u32_t*)value; |
||||
s32_t* value_s32 = (s32_t*)value; |
||||
u16_t value_len; |
||||
|
||||
switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) |
||||
{ |
||||
case 1: /* ifIndex */ |
||||
*value_s32 = netif_to_num(netif); |
||||
value_len = sizeof(*value_s32); |
||||
break; |
||||
case 2: /* ifDescr */ |
||||
value_len = sizeof(netif->name); |
||||
MEMCPY(value, netif->name, value_len); |
||||
break; |
||||
case 3: /* ifType */ |
||||
*value_s32 = netif->link_type; |
||||
value_len = sizeof(*value_s32); |
||||
break; |
||||
case 4: /* ifMtu */ |
||||
*value_s32 = netif->mtu; |
||||
value_len = sizeof(*value_s32); |
||||
break; |
||||
case 5: /* ifSpeed */ |
||||
*value_u32 = netif->link_speed; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 6: /* ifPhysAddress */ |
||||
value_len = sizeof(netif->hwaddr); |
||||
MEMCPY(value, &netif->hwaddr, value_len); |
||||
break; |
||||
case 7: /* ifAdminStatus */ |
||||
if (netif_is_up(netif)) { |
||||
*value_s32 = iftable_ifOperStatus_up; |
||||
} else { |
||||
*value_s32 = iftable_ifOperStatus_down; |
||||
} |
||||
value_len = sizeof(*value_s32); |
||||
break; |
||||
case 8: /* ifOperStatus */ |
||||
if (netif_is_up(netif)) { |
||||
if (netif_is_link_up(netif)) { |
||||
*value_s32 = iftable_ifAdminStatus_up; |
||||
} else { |
||||
*value_s32 = iftable_ifAdminStatus_lowerLayerDown; |
||||
} |
||||
} else { |
||||
*value_s32 = iftable_ifAdminStatus_down; |
||||
} |
||||
value_len = sizeof(*value_s32); |
||||
break; |
||||
case 9: /* ifLastChange */ |
||||
*value_u32 = netif->ts; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 10: /* ifInOctets */ |
||||
*value_u32 = netif->mib2_counters.ifinoctets; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 11: /* ifInUcastPkts */ |
||||
*value_u32 = netif->mib2_counters.ifinucastpkts; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 12: /* ifInNUcastPkts */ |
||||
*value_u32 = netif->mib2_counters.ifinnucastpkts; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 13: /* ifInDiscards */ |
||||
*value_u32 = netif->mib2_counters.ifindiscards; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 14: /* ifInErrors */ |
||||
*value_u32 = netif->mib2_counters.ifinerrors; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 15: /* ifInUnkownProtos */ |
||||
*value_u32 = netif->mib2_counters.ifinunknownprotos; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 16: /* ifOutOctets */ |
||||
*value_u32 = netif->mib2_counters.ifoutoctets; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 17: /* ifOutUcastPkts */ |
||||
*value_u32 = netif->mib2_counters.ifoutucastpkts; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 18: /* ifOutNUcastPkts */ |
||||
*value_u32 = netif->mib2_counters.ifoutnucastpkts; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 19: /* ifOutDiscarts */ |
||||
*value_u32 = netif->mib2_counters.ifoutdiscards; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 20: /* ifOutErrors */ |
||||
*value_u32 = netif->mib2_counters.ifouterrors; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
case 21: /* ifOutQLen */ |
||||
*value_u32 = iftable_ifOutQLen; |
||||
value_len = sizeof(*value_u32); |
||||
break; |
||||
/** @note returning zeroDotZero (0.0) no media specific MIB support */ |
||||
case 22: /* ifSpecific */ |
||||
value_len = snmp_zero_dot_zero.len * sizeof(u32_t); |
||||
MEMCPY(value, snmp_zero_dot_zero.id, value_len); |
||||
break; |
||||
default: |
||||
return 0; |
||||
} |
||||
|
||||
return value_len; |
||||
} |
||||
|
||||
#if !SNMP_SAFE_REQUESTS |
||||
|
||||
static snmp_err_t |
||||
interfaces_Table_set_test(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
|
||||
/* stack should never call this method for another column,
|
||||
because all other columns are set to readonly */ |
||||
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); |
||||
LWIP_UNUSED_ARG(len); |
||||
|
||||
if (*sint_ptr == 1 || *sint_ptr == 2) |
||||
{ |
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
return SNMP_ERR_WRONGVALUE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
interfaces_Table_set_value(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
struct netif *netif = (struct netif*)instance->reference.ptr; |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
|
||||
/* stack should never call this method for another column,
|
||||
because all other columns are set to readonly */ |
||||
LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); |
||||
LWIP_UNUSED_ARG(len); |
||||
|
||||
if (*sint_ptr == 1) { |
||||
netif_set_up(netif); |
||||
} else if (*sint_ptr == 2) { |
||||
netif_set_down(netif); |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
#endif /* SNMP_SAFE_REQUESTS */ |
||||
|
||||
static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); |
||||
|
||||
static const struct snmp_table_col_def interfaces_Table_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ |
||||
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ |
||||
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ |
||||
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ |
||||
{ 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ |
||||
{ 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ |
||||
#if !SNMP_SAFE_REQUESTS |
||||
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ |
||||
#else |
||||
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ |
||||
#endif |
||||
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ |
||||
{ 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ |
||||
{ 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ |
||||
{ 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ |
||||
{ 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ |
||||
{ 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ |
||||
{ 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ |
||||
{ 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ |
||||
{ 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ |
||||
{ 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ |
||||
{ 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ |
||||
{ 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ |
||||
{ 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ |
||||
{ 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ |
||||
{ 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ |
||||
}; |
||||
|
||||
#if !SNMP_SAFE_REQUESTS |
||||
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( |
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); |
||||
#else |
||||
static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( |
||||
2, interfaces_Table_columns,
|
||||
interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance,
|
||||
interfaces_Table_get_value, NULL, NULL); |
||||
#endif |
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE(1, interfaces_Number) |
||||
CREATE_LWIP_SYNC_NODE(2, interfaces_Table) |
||||
|
||||
static const struct snmp_node* const interface_nodes[] = { |
||||
&SYNC_NODE_NAME(interfaces_Number).node.node, |
||||
&SYNC_NODE_NAME(interfaces_Table).node.node |
||||
}; |
||||
|
||||
const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ |
||||
@ -1,743 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) IP objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/stats.h" |
||||
#include "lwip/netif.h" |
||||
#include "lwip/ip.h" |
||||
#include "lwip/etharp.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
#if LWIP_IPV4 |
||||
/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ |
||||
|
||||
static s16_t
|
||||
ip_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
s32_t* sint_ptr = (s32_t*)value; |
||||
u32_t* uint_ptr = (u32_t*)value; |
||||
|
||||
switch (instance->node->oid) { |
||||
case 1: /* ipForwarding */ |
||||
#if IP_FORWARD |
||||
/* forwarding */ |
||||
*sint_ptr = 1; |
||||
#else |
||||
/* not-forwarding */ |
||||
*sint_ptr = 2; |
||||
#endif |
||||
return sizeof(*sint_ptr); |
||||
case 2: /* ipDefaultTTL */ |
||||
*sint_ptr = IP_DEFAULT_TTL; |
||||
return sizeof(*sint_ptr); |
||||
case 3: /* ipInReceives */ |
||||
*uint_ptr = STATS_GET(mib2.ipinreceives); |
||||
return sizeof(*uint_ptr); |
||||
case 4: /* ipInHdrErrors */ |
||||
*uint_ptr = STATS_GET(mib2.ipinhdrerrors); |
||||
return sizeof(*uint_ptr); |
||||
case 5: /* ipInAddrErrors */ |
||||
*uint_ptr = STATS_GET(mib2.ipinaddrerrors); |
||||
return sizeof(*uint_ptr); |
||||
case 6: /* ipForwDatagrams */ |
||||
*uint_ptr = STATS_GET(mib2.ipforwdatagrams); |
||||
return sizeof(*uint_ptr); |
||||
case 7: /* ipInUnknownProtos */ |
||||
*uint_ptr = STATS_GET(mib2.ipinunknownprotos); |
||||
return sizeof(*uint_ptr); |
||||
case 8: /* ipInDiscards */ |
||||
*uint_ptr = STATS_GET(mib2.ipindiscards); |
||||
return sizeof(*uint_ptr); |
||||
case 9: /* ipInDelivers */ |
||||
*uint_ptr = STATS_GET(mib2.ipindelivers); |
||||
return sizeof(*uint_ptr); |
||||
case 10: /* ipOutRequests */ |
||||
*uint_ptr = STATS_GET(mib2.ipoutrequests); |
||||
return sizeof(*uint_ptr); |
||||
case 11: /* ipOutDiscards */ |
||||
*uint_ptr = STATS_GET(mib2.ipoutdiscards); |
||||
return sizeof(*uint_ptr); |
||||
case 12: /* ipOutNoRoutes */ |
||||
*uint_ptr = STATS_GET(mib2.ipoutnoroutes); |
||||
return sizeof(*uint_ptr); |
||||
case 13: /* ipReasmTimeout */ |
||||
#if IP_REASSEMBLY |
||||
*sint_ptr = IP_REASS_MAXAGE; |
||||
#else |
||||
*sint_ptr = 0; |
||||
#endif |
||||
return sizeof(*sint_ptr); |
||||
case 14: /* ipReasmReqds */ |
||||
*uint_ptr = STATS_GET(mib2.ipreasmreqds); |
||||
return sizeof(*uint_ptr); |
||||
case 15: /* ipReasmOKs */ |
||||
*uint_ptr = STATS_GET(mib2.ipreasmoks); |
||||
return sizeof(*uint_ptr); |
||||
case 16: /* ipReasmFails */ |
||||
*uint_ptr = STATS_GET(mib2.ipreasmfails); |
||||
return sizeof(*uint_ptr); |
||||
case 17: /* ipFragOKs */ |
||||
*uint_ptr = STATS_GET(mib2.ipfragoks); |
||||
return sizeof(*uint_ptr); |
||||
case 18: /* ipFragFails */ |
||||
*uint_ptr = STATS_GET(mib2.ipfragfails); |
||||
return sizeof(*uint_ptr); |
||||
case 19: /* ipFragCreates */ |
||||
*uint_ptr = STATS_GET(mib2.ipfragcreates); |
||||
return sizeof(*uint_ptr); |
||||
case 23: /* ipRoutingDiscards: not supported -> always 0 */ |
||||
*uint_ptr = 0; |
||||
return sizeof(*uint_ptr); |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); |
||||
break; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* Test ip object value before setting. |
||||
* |
||||
* @param od is the object definition |
||||
* @param len return value space (in bytes) |
||||
* @param value points to (varbind) space to copy value from. |
||||
* |
||||
* @note we allow set if the value matches the hardwired value, |
||||
* otherwise return badvalue. |
||||
*/ |
||||
static snmp_err_t |
||||
ip_set_test(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
snmp_err_t ret = SNMP_ERR_WRONGVALUE; |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
|
||||
LWIP_UNUSED_ARG(len); |
||||
switch (instance->node->oid) { |
||||
case 1: /* ipForwarding */ |
||||
#if IP_FORWARD |
||||
/* forwarding */ |
||||
if (*sint_ptr == 1) |
||||
#else |
||||
/* not-forwarding */ |
||||
if (*sint_ptr == 2) |
||||
#endif |
||||
{ |
||||
ret = SNMP_ERR_NOERROR; |
||||
} |
||||
break; |
||||
case 2: /* ipDefaultTTL */ |
||||
if (*sint_ptr == IP_DEFAULT_TTL) { |
||||
ret = SNMP_ERR_NOERROR; |
||||
} |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); |
||||
break; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_set_value(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
LWIP_UNUSED_ARG(instance); |
||||
LWIP_UNUSED_ARG(len); |
||||
LWIP_UNUSED_ARG(value); |
||||
/* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ |
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
/* --- ipAddrTable --- */ |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff } /* IP D */ |
||||
}; |
||||
|
||||
static snmp_err_t |
||||
ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
switch (*column) { |
||||
case 1: /* ipAdEntAddr */ |
||||
value->u32 = netif_ip4_addr(netif)->addr; |
||||
break; |
||||
case 2: /* ipAdEntIfIndex */ |
||||
value->u32 = netif_to_num(netif); |
||||
break; |
||||
case 3: /* ipAdEntNetMask */ |
||||
value->u32 = netif_ip4_netmask(netif)->addr; |
||||
break; |
||||
case 4: /* ipAdEntBcastAddr */ |
||||
/* lwIP oddity, there's no broadcast
|
||||
address in the netif we can rely on */ |
||||
value->u32 = IPADDR_BROADCAST & 1; |
||||
break; |
||||
case 5: /* ipAdEntReasmMaxSize */ |
||||
#if IP_REASSEMBLY |
||||
/* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs,
|
||||
* but only if receiving one fragmented packet at a time. |
||||
* The current solution is to calculate for 2 simultaneous packets... |
||||
*/ |
||||
value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS/2) * |
||||
(PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); |
||||
#else |
||||
/** @todo returning MTU would be a bad thing and
|
||||
returning a wild guess like '576' isn't good either */ |
||||
value->u32 = 0; |
||||
#endif |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_AddrTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip4_addr_t ip; |
||||
struct netif *netif; |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get IP from incoming OID */ |
||||
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ |
||||
|
||||
/* find netif with requested ip */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { |
||||
/* fill in object properties */ |
||||
return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); |
||||
} |
||||
|
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_AddrTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct netif *netif; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; |
||||
snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); |
||||
|
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return ip_AddrTable_get_cell_value_core((struct netif*)state.reference, column, value, value_len); |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* --- ipRouteTable --- */ |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff }, /* IP D */ |
||||
}; |
||||
|
||||
static snmp_err_t |
||||
ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
switch (*column) { |
||||
case 1: /* ipRouteDest */ |
||||
if (default_route) { |
||||
/* default rte has 0.0.0.0 dest */ |
||||
value->u32 = IP4_ADDR_ANY->addr; |
||||
} else { |
||||
/* netifs have netaddress dest */ |
||||
ip4_addr_t tmp; |
||||
ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); |
||||
value->u32 = tmp.addr; |
||||
} |
||||
break; |
||||
case 2: /* ipRouteIfIndex */ |
||||
value->u32 = netif_to_num(netif); |
||||
break; |
||||
case 3: /* ipRouteMetric1 */ |
||||
if (default_route) { |
||||
value->s32 = 1; /* default */ |
||||
} else { |
||||
value->s32 = 0; /* normal */ |
||||
} |
||||
break; |
||||
case 4: /* ipRouteMetric2 */ |
||||
case 5: /* ipRouteMetric3 */ |
||||
case 6: /* ipRouteMetric4 */ |
||||
value->s32 = -1; /* none */ |
||||
break; |
||||
case 7: /* ipRouteNextHop */ |
||||
if (default_route) { |
||||
/* default rte: gateway */ |
||||
value->u32 = netif_ip4_gw(netif)->addr; |
||||
} else { |
||||
/* other rtes: netif ip_addr */ |
||||
value->u32 = netif_ip4_addr(netif)->addr; |
||||
} |
||||
break; |
||||
case 8: /* ipRouteType */ |
||||
if (default_route) { |
||||
/* default rte is indirect */ |
||||
value->u32 = 4; /* indirect */ |
||||
} else { |
||||
/* other rtes are direct */ |
||||
value->u32 = 3; /* direct */ |
||||
} |
||||
break; |
||||
case 9: /* ipRouteProto */ |
||||
/* locally defined routes */ |
||||
value->u32 = 2; /* local */ |
||||
break; |
||||
case 10: /* ipRouteAge */ |
||||
/* @todo (sysuptime - timestamp last change) / 100 */ |
||||
value->u32 = 0; |
||||
break; |
||||
case 11: /* ipRouteMask */ |
||||
if (default_route) { |
||||
/* default rte use 0.0.0.0 mask */ |
||||
value->u32 = IP4_ADDR_ANY->addr; |
||||
} else { |
||||
/* other rtes use netmask */ |
||||
value->u32 = netif_ip4_netmask(netif)->addr; |
||||
} |
||||
break; |
||||
case 12: /* ipRouteMetric5 */ |
||||
value->s32 = -1; /* none */ |
||||
break; |
||||
case 13: /* ipRouteInfo */ |
||||
value->const_ptr = snmp_zero_dot_zero.id; |
||||
*value_len = snmp_zero_dot_zero.len * sizeof(u32_t); |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_RouteTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip4_addr_t test_ip; |
||||
struct netif *netif; |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get IP and port from incoming OID */ |
||||
snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ |
||||
|
||||
/* default route is on default netif */ |
||||
if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { |
||||
/* fill in object properties */ |
||||
return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); |
||||
} |
||||
|
||||
/* find netif with requested route */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
ip4_addr_t dst; |
||||
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); |
||||
|
||||
if (ip4_addr_cmp(&dst, &test_ip)) { |
||||
/* fill in object properties */ |
||||
return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); |
||||
} |
||||
|
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_RouteTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct netif *netif; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; |
||||
u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); |
||||
|
||||
/* check default route */ |
||||
if (netif_default != NULL) { |
||||
snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[0]); |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); |
||||
} |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
netif = netif_list; |
||||
while (netif != NULL) { |
||||
ip4_addr_t dst; |
||||
ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
if (!ip4_addr_isany_val(dst)) { |
||||
snmp_ip4_to_oid(&dst, &test_oid[0]); |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); |
||||
} |
||||
|
||||
netif = netif->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
ip4_addr_t dst; |
||||
snmp_oid_to_ip4(&result_temp[0], &dst); |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return ip_RouteTable_get_cell_value_core((struct netif*)state.reference, ip4_addr_isany_val(dst), column, value, value_len); |
||||
} else { |
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
} |
||||
|
||||
#if LWIP_ARP && LWIP_IPV4 |
||||
/* --- ipNetToMediaTable --- */ |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { |
||||
{ 1, 0xff }, /* IfIndex */ |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff } /* IP D */ |
||||
}; |
||||
|
||||
static snmp_err_t |
||||
ip_NetToMediaTable_get_cell_value_core(u8_t arp_table_index, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip4_addr_t *ip; |
||||
struct netif *netif; |
||||
struct eth_addr *ethaddr; |
||||
|
||||
etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); |
||||
|
||||
/* value */ |
||||
switch (*column) { |
||||
case 1: /* atIfIndex / ipNetToMediaIfIndex */ |
||||
value->u32 = netif_to_num(netif); |
||||
break; |
||||
case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ |
||||
value->ptr = ethaddr; |
||||
*value_len = sizeof(*ethaddr); |
||||
break; |
||||
case 3: /* atNetAddress / ipNetToMediaNetAddress */ |
||||
value->u32 = ip->addr; |
||||
break; |
||||
case 4: /* ipNetToMediaType */ |
||||
value->u32 = 3; /* dynamic*/ |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_NetToMediaTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip4_addr_t ip_in; |
||||
u8_t netif_index; |
||||
u8_t i; |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get IP from incoming OID */ |
||||
netif_index = (u8_t)row_oid[0]; |
||||
snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ |
||||
|
||||
/* find requested entry */ |
||||
for (i=0; i<ARP_TABLE_SIZE; i++) { |
||||
ip4_addr_t *ip; |
||||
struct netif *netif; |
||||
struct eth_addr *ethaddr; |
||||
|
||||
if (etharp_get_entry(i, &ip, &netif, ðaddr)) { |
||||
if ((netif_index == netif_to_num(netif)) && ip4_addr_cmp(&ip_in, ip)) { |
||||
/* fill in object properties */ |
||||
return ip_NetToMediaTable_get_cell_value_core(i, column, value, value_len); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
u8_t i; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
for (i=0; i<ARP_TABLE_SIZE; i++) { |
||||
ip4_addr_t *ip; |
||||
struct netif *netif; |
||||
struct eth_addr *ethaddr; |
||||
|
||||
if (etharp_get_entry(i, &ip, &netif, ðaddr)) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; |
||||
|
||||
test_oid[0] = netif_to_num(netif); |
||||
snmp_ip4_to_oid(ip, &test_oid[1]); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), (void*)(size_t)i); |
||||
} |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return ip_NetToMediaTable_get_cell_value_core((u8_t)(size_t)state.reference, column, value, value_len); |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
#endif /* LWIP_ARP && LWIP_IPV4 */ |
||||
|
||||
static const struct snmp_scalar_node ip_Forwarding = SNMP_SCALAR_CREATE_NODE(1, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value); |
||||
static const struct snmp_scalar_node ip_DefaultTTL = SNMP_SCALAR_CREATE_NODE(2, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value); |
||||
static const struct snmp_scalar_node ip_InReceives = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_InHdrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_InAddrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_ForwDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_InUnknownProtos = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_InDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_InDelivers = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_OutRequests = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_OutDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_OutNoRoutes = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_ReasmTimeout = SNMP_SCALAR_CREATE_NODE_READONLY(13, SNMP_ASN1_TYPE_INTEGER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_ReasmReqds = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_ReasmOKs = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_ReasmFails = SNMP_SCALAR_CREATE_NODE_READONLY(16, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_FragOKs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_FragFails = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_FragCreates = SNMP_SCALAR_CREATE_NODE_READONLY(19, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
static const struct snmp_scalar_node ip_RoutingDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(23, SNMP_ASN1_TYPE_COUNTER, ip_get_value); |
||||
|
||||
static const struct snmp_table_simple_col_def ip_AddrTable_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntAddr */ |
||||
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntIfIndex */ |
||||
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntNetMask */ |
||||
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntBcastAddr */ |
||||
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipAdEntReasmMaxSize */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node ip_AddrTable = SNMP_TABLE_CREATE_SIMPLE(20, ip_AddrTable_columns, ip_AddrTable_get_cell_value, ip_AddrTable_get_next_cell_instance_and_value); |
||||
|
||||
static const struct snmp_table_simple_col_def ip_RouteTable_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteDest */ |
||||
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteIfIndex */ |
||||
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric1 */ |
||||
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric2 */ |
||||
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric3 */ |
||||
{ 6, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric4 */ |
||||
{ 7, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteNextHop */ |
||||
{ 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteType */ |
||||
{ 9, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteProto */ |
||||
{ 10, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteAge */ |
||||
{ 11, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteMask */ |
||||
{ 12, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric5 */ |
||||
{ 13, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_VARIANT_VALUE_TYPE_PTR } /* ipRouteInfo */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node ip_RouteTable = SNMP_TABLE_CREATE_SIMPLE(21, ip_RouteTable_columns, ip_RouteTable_get_cell_value, ip_RouteTable_get_next_cell_instance_and_value); |
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
#if LWIP_ARP && LWIP_IPV4 |
||||
static const struct snmp_table_simple_col_def ip_NetToMediaTable_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaIfIndex */ |
||||
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* ipNetToMediaPhysAddress */ |
||||
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaNetAddress */ |
||||
{ 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipNetToMediaType */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREATE_SIMPLE(22, ip_NetToMediaTable_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value); |
||||
#endif /* LWIP_ARP && LWIP_IPV4 */ |
||||
|
||||
#if LWIP_IPV4 |
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding) |
||||
CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL) |
||||
CREATE_LWIP_SYNC_NODE( 3, ip_InReceives) |
||||
CREATE_LWIP_SYNC_NODE( 4, ip_InHdrErrors) |
||||
CREATE_LWIP_SYNC_NODE( 5, ip_InAddrErrors) |
||||
CREATE_LWIP_SYNC_NODE( 6, ip_ForwDatagrams) |
||||
CREATE_LWIP_SYNC_NODE( 7, ip_InUnknownProtos) |
||||
CREATE_LWIP_SYNC_NODE( 8, ip_InDiscards) |
||||
CREATE_LWIP_SYNC_NODE( 9, ip_InDelivers) |
||||
CREATE_LWIP_SYNC_NODE(10, ip_OutRequests) |
||||
CREATE_LWIP_SYNC_NODE(11, ip_OutDiscards) |
||||
CREATE_LWIP_SYNC_NODE(12, ip_OutNoRoutes) |
||||
CREATE_LWIP_SYNC_NODE(13, ip_ReasmTimeout) |
||||
CREATE_LWIP_SYNC_NODE(14, ip_ReasmReqds) |
||||
CREATE_LWIP_SYNC_NODE(15, ip_ReasmOKs) |
||||
CREATE_LWIP_SYNC_NODE(15, ip_ReasmFails) |
||||
CREATE_LWIP_SYNC_NODE(17, ip_FragOKs) |
||||
CREATE_LWIP_SYNC_NODE(18, ip_FragFails) |
||||
CREATE_LWIP_SYNC_NODE(19, ip_FragCreates) |
||||
CREATE_LWIP_SYNC_NODE(20, ip_AddrTable) |
||||
CREATE_LWIP_SYNC_NODE(21, ip_RouteTable) |
||||
#if LWIP_ARP |
||||
CREATE_LWIP_SYNC_NODE(22, ip_NetToMediaTable) |
||||
#endif /* LWIP_ARP */ |
||||
CREATE_LWIP_SYNC_NODE(23, ip_RoutingDiscards) |
||||
|
||||
static const struct snmp_node* const ip_nodes[] = { |
||||
&SYNC_NODE_NAME(ip_Forwarding).node.node, |
||||
&SYNC_NODE_NAME(ip_DefaultTTL).node.node, |
||||
&SYNC_NODE_NAME(ip_InReceives).node.node, |
||||
&SYNC_NODE_NAME(ip_InHdrErrors).node.node, |
||||
&SYNC_NODE_NAME(ip_InAddrErrors).node.node, |
||||
&SYNC_NODE_NAME(ip_ForwDatagrams).node.node, |
||||
&SYNC_NODE_NAME(ip_InUnknownProtos).node.node, |
||||
&SYNC_NODE_NAME(ip_InDiscards).node.node, |
||||
&SYNC_NODE_NAME(ip_InDelivers).node.node, |
||||
&SYNC_NODE_NAME(ip_OutRequests).node.node, |
||||
&SYNC_NODE_NAME(ip_OutDiscards).node.node, |
||||
&SYNC_NODE_NAME(ip_OutNoRoutes).node.node, |
||||
&SYNC_NODE_NAME(ip_ReasmTimeout).node.node, |
||||
&SYNC_NODE_NAME(ip_ReasmReqds).node.node, |
||||
&SYNC_NODE_NAME(ip_ReasmOKs).node.node, |
||||
&SYNC_NODE_NAME(ip_ReasmFails).node.node, |
||||
&SYNC_NODE_NAME(ip_FragOKs).node.node, |
||||
&SYNC_NODE_NAME(ip_FragFails).node.node, |
||||
&SYNC_NODE_NAME(ip_FragCreates).node.node, |
||||
&SYNC_NODE_NAME(ip_AddrTable).node.node, |
||||
&SYNC_NODE_NAME(ip_RouteTable).node.node, |
||||
#if LWIP_ARP |
||||
&SYNC_NODE_NAME(ip_NetToMediaTable).node.node, |
||||
#endif /* LWIP_ARP */ |
||||
&SYNC_NODE_NAME(ip_RoutingDiscards).node.node |
||||
}; |
||||
|
||||
const struct snmp_tree_node snmp_mib2_ip_root = SNMP_CREATE_TREE_NODE(4, ip_nodes); |
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
/* --- at .1.3.6.1.2.1.3 ----------------------------------------------------- */ |
||||
|
||||
#if LWIP_ARP && LWIP_IPV4 |
||||
/* at node table is a subset of ip_nettomedia table (same rows but less columns) */ |
||||
static const struct snmp_table_simple_col_def at_Table_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* atIfIndex */ |
||||
{ 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* atPhysAddress */ |
||||
{ 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 } /* atNetAddress */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value); |
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE(1, at_Table) |
||||
|
||||
static const struct snmp_node* const at_nodes[] = { |
||||
&SYNC_NODE_NAME(at_Table).node.node |
||||
}; |
||||
|
||||
const struct snmp_tree_node snmp_mib2_at_root = SNMP_CREATE_TREE_NODE(3, at_nodes); |
||||
#endif /* LWIP_ARP && LWIP_IPV4 */ |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ |
||||
@ -1,227 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) SNMP objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 |
||||
|
||||
#define MIB2_AUTH_TRAPS_ENABLED 1 |
||||
#define MIB2_AUTH_TRAPS_DISABLED 2 |
||||
|
||||
/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ |
||||
static s16_t |
||||
snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) |
||||
{ |
||||
u32_t *uint_ptr = (u32_t*)value; |
||||
switch (node->oid) { |
||||
case 1: /* snmpInPkts */ |
||||
*uint_ptr = snmp_stats.inpkts; |
||||
break; |
||||
case 2: /* snmpOutPkts */ |
||||
*uint_ptr = snmp_stats.outpkts; |
||||
break; |
||||
case 3: /* snmpInBadVersions */ |
||||
*uint_ptr = snmp_stats.inbadversions; |
||||
break; |
||||
case 4: /* snmpInBadCommunityNames */ |
||||
*uint_ptr = snmp_stats.inbadcommunitynames; |
||||
break; |
||||
case 5: /* snmpInBadCommunityUses */ |
||||
*uint_ptr = snmp_stats.inbadcommunityuses; |
||||
break; |
||||
case 6: /* snmpInASNParseErrs */ |
||||
*uint_ptr = snmp_stats.inasnparseerrs; |
||||
break; |
||||
case 8: /* snmpInTooBigs */ |
||||
*uint_ptr = snmp_stats.intoobigs; |
||||
break; |
||||
case 9: /* snmpInNoSuchNames */ |
||||
*uint_ptr = snmp_stats.innosuchnames; |
||||
break; |
||||
case 10: /* snmpInBadValues */ |
||||
*uint_ptr = snmp_stats.inbadvalues; |
||||
break; |
||||
case 11: /* snmpInReadOnlys */ |
||||
*uint_ptr = snmp_stats.inreadonlys; |
||||
break; |
||||
case 12: /* snmpInGenErrs */ |
||||
*uint_ptr = snmp_stats.ingenerrs; |
||||
break; |
||||
case 13: /* snmpInTotalReqVars */ |
||||
*uint_ptr = snmp_stats.intotalreqvars; |
||||
break; |
||||
case 14: /* snmpInTotalSetVars */ |
||||
*uint_ptr = snmp_stats.intotalsetvars; |
||||
break; |
||||
case 15: /* snmpInGetRequests */ |
||||
*uint_ptr = snmp_stats.ingetrequests; |
||||
break; |
||||
case 16: /* snmpInGetNexts */ |
||||
*uint_ptr = snmp_stats.ingetnexts; |
||||
break; |
||||
case 17: /* snmpInSetRequests */ |
||||
*uint_ptr = snmp_stats.insetrequests; |
||||
break; |
||||
case 18: /* snmpInGetResponses */ |
||||
*uint_ptr = snmp_stats.ingetresponses; |
||||
break; |
||||
case 19: /* snmpInTraps */ |
||||
*uint_ptr = snmp_stats.intraps; |
||||
break; |
||||
case 20: /* snmpOutTooBigs */ |
||||
*uint_ptr = snmp_stats.outtoobigs; |
||||
break; |
||||
case 21: /* snmpOutNoSuchNames */ |
||||
*uint_ptr = snmp_stats.outnosuchnames; |
||||
break; |
||||
case 22: /* snmpOutBadValues */ |
||||
*uint_ptr = snmp_stats.outbadvalues; |
||||
break; |
||||
case 24: /* snmpOutGenErrs */ |
||||
*uint_ptr = snmp_stats.outgenerrs; |
||||
break; |
||||
case 25: /* snmpOutGetRequests */ |
||||
*uint_ptr = snmp_stats.outgetrequests; |
||||
break; |
||||
case 26: /* snmpOutGetNexts */ |
||||
*uint_ptr = snmp_stats.outgetnexts; |
||||
break; |
||||
case 27: /* snmpOutSetRequests */ |
||||
*uint_ptr = snmp_stats.outsetrequests; |
||||
break; |
||||
case 28: /* snmpOutGetResponses */ |
||||
*uint_ptr = snmp_stats.outgetresponses; |
||||
break; |
||||
case 29: /* snmpOutTraps */ |
||||
*uint_ptr = snmp_stats.outtraps; |
||||
break; |
||||
case 30: /* snmpEnableAuthenTraps */ |
||||
if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { |
||||
*uint_ptr = MIB2_AUTH_TRAPS_DISABLED; |
||||
} else { |
||||
*uint_ptr = MIB2_AUTH_TRAPS_ENABLED; |
||||
} |
||||
break; |
||||
case 31: /* snmpSilentDrops */ |
||||
*uint_ptr = 0; /* not supported */ |
||||
break; |
||||
case 32: /* snmpProxyDrops */ |
||||
*uint_ptr = 0; /* not supported */ |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); |
||||
return 0; |
||||
} |
||||
|
||||
return sizeof(*uint_ptr); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) |
||||
{ |
||||
snmp_err_t ret = SNMP_ERR_WRONGVALUE; |
||||
LWIP_UNUSED_ARG(len); |
||||
|
||||
if (node->oid == 30) { |
||||
/* snmpEnableAuthenTraps */ |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
|
||||
/* we should have writable non-volatile mem here */ |
||||
if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { |
||||
ret = SNMP_ERR_NOERROR; |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) |
||||
{ |
||||
LWIP_UNUSED_ARG(len); |
||||
|
||||
if (node->oid == 30) { |
||||
/* snmpEnableAuthenTraps */ |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { |
||||
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); |
||||
} else { |
||||
snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); |
||||
} |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */
|
||||
static const struct snmp_scalar_array_node_def snmp_nodes[] = { |
||||
{ 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ |
||||
{ 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ |
||||
{ 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ |
||||
{ 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ |
||||
{ 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ |
||||
{ 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ |
||||
{ 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ |
||||
{ 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ |
||||
{10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ |
||||
{11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ |
||||
{12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ |
||||
{13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ |
||||
{14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ |
||||
{15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ |
||||
{16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ |
||||
{17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ |
||||
{18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ |
||||
{19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ |
||||
{20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ |
||||
{21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ |
||||
{22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ |
||||
{24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ |
||||
{25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ |
||||
{26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ |
||||
{27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ |
||||
{28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ |
||||
{29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ |
||||
{30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ |
||||
{31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ |
||||
{32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ |
||||
}; |
||||
|
||||
const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ |
||||
@ -1,377 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) SYSTEM objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/sys.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ |
||||
|
||||
/** mib-2.system.sysDescr */ |
||||
static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; |
||||
static const u8_t* sysdescr = sysdescr_default; |
||||
static const u16_t* sysdescr_len = NULL; /* use strlen for determining len */ |
||||
|
||||
/** mib-2.system.sysContact */ |
||||
static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; |
||||
static const u8_t* syscontact = syscontact_default; |
||||
static const u16_t* syscontact_len = NULL; /* use strlen for determining len */ |
||||
static u8_t* syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ |
||||
static u16_t* syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ |
||||
static u16_t syscontact_bufsize = 0; /* 0=not writable */ |
||||
|
||||
/** mib-2.system.sysName */ |
||||
static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; |
||||
static const u8_t* sysname = sysname_default; |
||||
static const u16_t* sysname_len = NULL; /* use strlen for determining len */ |
||||
static u8_t* sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ |
||||
static u16_t* sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ |
||||
static u16_t sysname_bufsize = 0; /* 0=not writable */ |
||||
|
||||
/** mib-2.system.sysLocation */ |
||||
static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; |
||||
static const u8_t* syslocation = syslocation_default; |
||||
static const u16_t* syslocation_len = NULL; /* use strlen for determining len */ |
||||
static u8_t* syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ |
||||
static u16_t* syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ |
||||
static u16_t syslocation_bufsize = 0; /* 0=not writable */ |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* Initializes sysDescr pointers. |
||||
* |
||||
* @param str if non-NULL then copy str pointer |
||||
* @param len points to string length, excluding zero terminator |
||||
*/ |
||||
void |
||||
snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) |
||||
{ |
||||
if (str != NULL) { |
||||
sysdescr = str; |
||||
sysdescr_len = len; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* Initializes sysContact pointers |
||||
* |
||||
* @param ocstr if non-NULL then copy str pointer |
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated. |
||||
* @param bufsize size of the buffer in bytes. |
||||
* (this is required because the buffer can be overwritten by snmp-set) |
||||
* if ocstrlen is NULL buffer needs space for terminating 0 byte. |
||||
* otherwise complete buffer is used for string. |
||||
* if bufsize is set to 0, the value is regarded as read-only. |
||||
*/ |
||||
void |
||||
snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
syscontact = ocstr; |
||||
syscontact_wr = ocstr; |
||||
syscontact_len = ocstrlen; |
||||
syscontact_wr_len = ocstrlen; |
||||
syscontact_bufsize = bufsize; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* see \ref snmp_mib2_set_syscontact but set pointer to readonly memory |
||||
*/ |
||||
void |
||||
snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
syscontact = ocstr; |
||||
syscontact_len = ocstrlen; |
||||
syscontact_wr = NULL; |
||||
syscontact_wr_len = NULL; |
||||
syscontact_bufsize = 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* Initializes sysName pointers |
||||
* |
||||
* @param ocstr if non-NULL then copy str pointer |
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated. |
||||
* @param bufsize size of the buffer in bytes. |
||||
* (this is required because the buffer can be overwritten by snmp-set) |
||||
* if ocstrlen is NULL buffer needs space for terminating 0 byte. |
||||
* otherwise complete buffer is used for string. |
||||
* if bufsize is set to 0, the value is regarded as read-only. |
||||
*/ |
||||
void |
||||
snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
sysname = ocstr; |
||||
sysname_wr = ocstr; |
||||
sysname_len = ocstrlen; |
||||
sysname_wr_len = ocstrlen; |
||||
sysname_bufsize = bufsize; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* see \ref snmp_mib2_set_sysname but set pointer to readonly memory |
||||
*/ |
||||
void |
||||
snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
sysname = ocstr; |
||||
sysname_len = ocstrlen; |
||||
sysname_wr = NULL; |
||||
sysname_wr_len = NULL; |
||||
sysname_bufsize = 0; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* Initializes sysLocation pointers |
||||
* |
||||
* @param ocstr if non-NULL then copy str pointer |
||||
* @param ocstrlen points to string length, excluding zero terminator.
|
||||
* if set to NULL it is assumed that ocstr is NULL-terminated. |
||||
* @param bufsize size of the buffer in bytes. |
||||
* (this is required because the buffer can be overwritten by snmp-set) |
||||
* if ocstrlen is NULL buffer needs space for terminating 0 byte. |
||||
* otherwise complete buffer is used for string. |
||||
* if bufsize is set to 0, the value is regarded as read-only. |
||||
*/ |
||||
void |
||||
snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
syslocation = ocstr; |
||||
syslocation_wr = ocstr; |
||||
syslocation_len = ocstrlen; |
||||
syslocation_wr_len = ocstrlen; |
||||
syslocation_bufsize = bufsize; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_mib2 |
||||
* see \ref snmp_mib2_set_syslocation but set pointer to readonly memory |
||||
*/ |
||||
void |
||||
snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) |
||||
{ |
||||
if (ocstr != NULL) { |
||||
syslocation = ocstr; |
||||
syslocation_len = ocstrlen; |
||||
syslocation_wr = NULL; |
||||
syslocation_wr_len = NULL; |
||||
syslocation_bufsize = 0; |
||||
} |
||||
} |
||||
|
||||
|
||||
static s16_t |
||||
system_get_value(const struct snmp_scalar_array_node_def *node, void *value) |
||||
{ |
||||
const u8_t* var = NULL; |
||||
const s16_t* var_len; |
||||
u16_t result; |
||||
|
||||
switch (node->oid) { |
||||
case 1: /* sysDescr */ |
||||
var = sysdescr; |
||||
var_len = (const s16_t*)sysdescr_len; |
||||
break; |
||||
case 2: /* sysObjectID */ |
||||
{ |
||||
const struct snmp_obj_id* dev_enterprise_oid = snmp_get_device_enterprise_oid(); |
||||
MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); |
||||
return dev_enterprise_oid->len * sizeof(u32_t); |
||||
} |
||||
case 3: /* sysUpTime */ |
||||
MIB2_COPY_SYSUPTIME_TO((u32_t*)value); |
||||
return sizeof(u32_t); |
||||
case 4: /* sysContact */ |
||||
var = syscontact; |
||||
var_len = (const s16_t*)syscontact_len; |
||||
break; |
||||
case 5: /* sysName */ |
||||
var = sysname; |
||||
var_len = (const s16_t*)sysname_len; |
||||
break; |
||||
case 6: /* sysLocation */ |
||||
var = syslocation; |
||||
var_len = (const s16_t*)syslocation_len; |
||||
break; |
||||
case 7: /* sysServices */ |
||||
*(s32_t*)value = SNMP_SYSSERVICES; |
||||
return sizeof(s32_t); |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_get_value(): unknown id: %"S32_F"\n", node->oid)); |
||||
return 0; |
||||
} |
||||
|
||||
/* handle string values (OID 1,4,5 and 6) */ |
||||
LWIP_ASSERT("", (value != NULL)); |
||||
if (var_len == NULL) { |
||||
result = (s16_t)strlen((const char*)var); |
||||
} else { |
||||
result = *var_len; |
||||
} |
||||
MEMCPY(value, var, result); |
||||
return result; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) |
||||
{ |
||||
snmp_err_t ret = SNMP_ERR_WRONGVALUE; |
||||
const u16_t* var_bufsize = NULL; |
||||
const u16_t* var_wr_len; |
||||
|
||||
LWIP_UNUSED_ARG(value); |
||||
|
||||
switch (node->oid) { |
||||
case 4: /* sysContact */ |
||||
var_bufsize = &syscontact_bufsize; |
||||
var_wr_len = syscontact_wr_len; |
||||
break; |
||||
case 5: /* sysName */ |
||||
var_bufsize = &sysname_bufsize; |
||||
var_wr_len = sysname_wr_len; |
||||
break; |
||||
case 6: /* sysLocation */ |
||||
var_bufsize = &syslocation_bufsize; |
||||
var_wr_len = syslocation_wr_len; |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_test(): unknown id: %"S32_F"\n", node->oid)); |
||||
return ret; |
||||
} |
||||
|
||||
/* check if value is writable at all */ |
||||
if (*var_bufsize > 0) { |
||||
if (var_wr_len == NULL) { |
||||
/* we have to take the terminating 0 into account */ |
||||
if (len < *var_bufsize) { |
||||
ret = SNMP_ERR_NOERROR; |
||||
} |
||||
} else { |
||||
if (len <= *var_bufsize) { |
||||
ret = SNMP_ERR_NOERROR; |
||||
} |
||||
} |
||||
} else { |
||||
ret = SNMP_ERR_NOTWRITABLE; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) |
||||
{ |
||||
u8_t* var_wr = NULL; |
||||
u16_t* var_wr_len; |
||||
|
||||
switch (node->oid) { |
||||
case 4: /* sysContact */ |
||||
var_wr = syscontact_wr; |
||||
var_wr_len = syscontact_wr_len; |
||||
break; |
||||
case 5: /* sysName */ |
||||
var_wr = sysname_wr; |
||||
var_wr_len = sysname_wr_len; |
||||
break; |
||||
case 6: /* sysLocation */ |
||||
var_wr = syslocation_wr; |
||||
var_wr_len = syslocation_wr_len; |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("system_set_value(): unknown id: %"S32_F"\n", node->oid)); |
||||
return SNMP_ERR_GENERROR; |
||||
} |
||||
|
||||
/* no need to check size of target buffer, this was already done in set_test method */ |
||||
LWIP_ASSERT("", var_wr != NULL); |
||||
MEMCPY(var_wr, value, len); |
||||
|
||||
if (var_wr_len == NULL) { |
||||
/* add terminating 0 */ |
||||
var_wr[len] = 0; |
||||
} else { |
||||
*var_wr_len = len; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static const struct snmp_scalar_array_node_def system_nodes[] = { |
||||
{1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ |
||||
{2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ |
||||
{3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ |
||||
{4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ |
||||
{5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ |
||||
{6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ |
||||
{7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ |
||||
}; |
||||
|
||||
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); |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ |
||||
@ -1,594 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) TCP objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/tcp.h" |
||||
#include "lwip/priv/tcp_priv.h" |
||||
#include "lwip/stats.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ |
||||
|
||||
static s16_t
|
||||
tcp_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
u32_t *uint_ptr = (u32_t*)value; |
||||
s32_t *sint_ptr = (s32_t*)value; |
||||
|
||||
switch (instance->node->oid) { |
||||
case 1: /* tcpRtoAlgorithm, vanj(4) */ |
||||
*sint_ptr = 4; |
||||
return sizeof(*sint_ptr); |
||||
case 2: /* tcpRtoMin */ |
||||
/* @todo not the actual value, a guess,
|
||||
needs to be calculated */ |
||||
*sint_ptr = 1000; |
||||
return sizeof(*sint_ptr); |
||||
case 3: /* tcpRtoMax */ |
||||
/* @todo not the actual value, a guess,
|
||||
needs to be calculated */ |
||||
*sint_ptr = 60000; |
||||
return sizeof(*sint_ptr); |
||||
case 4: /* tcpMaxConn */ |
||||
*sint_ptr = MEMP_NUM_TCP_PCB; |
||||
return sizeof(*sint_ptr); |
||||
case 5: /* tcpActiveOpens */ |
||||
*uint_ptr = STATS_GET(mib2.tcpactiveopens); |
||||
return sizeof(*uint_ptr); |
||||
case 6: /* tcpPassiveOpens */ |
||||
*uint_ptr = STATS_GET(mib2.tcppassiveopens); |
||||
return sizeof(*uint_ptr); |
||||
case 7: /* tcpAttemptFails */ |
||||
*uint_ptr = STATS_GET(mib2.tcpattemptfails); |
||||
return sizeof(*uint_ptr); |
||||
case 8: /* tcpEstabResets */ |
||||
*uint_ptr = STATS_GET(mib2.tcpestabresets); |
||||
return sizeof(*uint_ptr); |
||||
case 9: /* tcpCurrEstab */ |
||||
{ |
||||
u16_t tcpcurrestab = 0; |
||||
struct tcp_pcb *pcb = tcp_active_pcbs; |
||||
while (pcb != NULL) { |
||||
if ((pcb->state == ESTABLISHED) || |
||||
(pcb->state == CLOSE_WAIT)) { |
||||
tcpcurrestab++; |
||||
} |
||||
pcb = pcb->next; |
||||
} |
||||
*uint_ptr = tcpcurrestab; |
||||
} |
||||
return sizeof(*uint_ptr); |
||||
case 10: /* tcpInSegs */ |
||||
*uint_ptr = STATS_GET(mib2.tcpinsegs); |
||||
return sizeof(*uint_ptr); |
||||
case 11: /* tcpOutSegs */ |
||||
*uint_ptr = STATS_GET(mib2.tcpoutsegs); |
||||
return sizeof(*uint_ptr); |
||||
case 12: /* tcpRetransSegs */ |
||||
*uint_ptr = STATS_GET(mib2.tcpretranssegs); |
||||
return sizeof(*uint_ptr); |
||||
case 14: /* tcpInErrs */ |
||||
*uint_ptr = STATS_GET(mib2.tcpinerrs); |
||||
return sizeof(*uint_ptr); |
||||
case 15: /* tcpOutRsts */ |
||||
*uint_ptr = STATS_GET(mib2.tcpoutrsts); |
||||
return sizeof(*uint_ptr); |
||||
case 17: /* tcpHCInSegs */ |
||||
memset(value, 0, 2*sizeof(u32_t)); /* not supported */ |
||||
return 2*sizeof(u32_t); |
||||
case 18: /* tcpHCOutSegs */ |
||||
memset(value, 0, 2*sizeof(u32_t)); /* not supported */ |
||||
return 2*sizeof(u32_t); |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); |
||||
break; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* --- tcpConnTable --- */ |
||||
|
||||
#if LWIP_IPV4 |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff }, /* IP D */ |
||||
{ 0, 0xffff }, /* Port */ |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff }, /* IP D */ |
||||
{ 0, 0xffff } /* Port */ |
||||
}; |
||||
|
||||
static snmp_err_t
|
||||
tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* value */ |
||||
switch (*column) { |
||||
case 1: /* tcpConnState */ |
||||
value->u32 = pcb->state + 1; |
||||
break; |
||||
case 2: /* tcpConnLocalAddress */ |
||||
value->u32 = ip_2_ip4(&pcb->local_ip)->addr; |
||||
break; |
||||
case 3: /* tcpConnLocalPort */ |
||||
value->u32 = pcb->local_port; |
||||
break; |
||||
case 4: /* tcpConnRemAddress */ |
||||
if (pcb->state == LISTEN) { |
||||
value->u32 = IP4_ADDR_ANY->addr; |
||||
} else { |
||||
value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; |
||||
} |
||||
break; |
||||
case 5: /* tcpConnRemPort */ |
||||
if (pcb->state == LISTEN) { |
||||
value->u32 = 0; |
||||
} else { |
||||
value->u32 = pcb->remote_port; |
||||
} |
||||
break; |
||||
default: |
||||
LWIP_ASSERT("invalid id", 0); |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
u8_t i; |
||||
ip4_addr_t local_ip; |
||||
ip4_addr_t remote_ip; |
||||
u16_t local_port; |
||||
u16_t remote_port; |
||||
struct tcp_pcb *pcb; |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get IPs and ports from incoming OID */ |
||||
snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ |
||||
local_port = (u16_t)row_oid[4]; |
||||
snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ |
||||
remote_port = (u16_t)row_oid[9]; |
||||
|
||||
/* find tcp_pcb with requested ips and ports */ |
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { |
||||
pcb = *tcp_pcb_lists[i]; |
||||
|
||||
while (pcb != NULL) { |
||||
/* do local IP and local port match? */ |
||||
if (IP_IS_V4_VAL(pcb->local_ip) && |
||||
ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { |
||||
|
||||
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ |
||||
if (pcb->state == LISTEN) { |
||||
if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY) && (remote_port == 0)) { |
||||
/* fill in object properties */ |
||||
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); |
||||
} |
||||
} else { |
||||
if (IP_IS_V4_VAL(pcb->remote_ip) && |
||||
ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { |
||||
/* fill in object properties */ |
||||
return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); |
||||
} |
||||
} |
||||
} |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
u8_t i; |
||||
struct tcp_pcb *pcb; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { |
||||
pcb = *tcp_pcb_lists[i]; |
||||
while (pcb != NULL) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; |
||||
|
||||
if (IP_IS_V4_VAL(pcb->local_ip)) { |
||||
snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); |
||||
test_oid[4] = pcb->local_port; |
||||
|
||||
/* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ |
||||
if (pcb->state == LISTEN) { |
||||
snmp_ip4_to_oid(IP4_ADDR_ANY, &test_oid[5]); |
||||
test_oid[9] = 0; |
||||
} else { |
||||
if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ |
||||
continue; |
||||
} |
||||
snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); |
||||
test_oid[9] = pcb->remote_port; |
||||
} |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); |
||||
} |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
/* --- tcpConnectionTable --- */ |
||||
|
||||
static snmp_err_t
|
||||
tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) |
||||
{ |
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
switch (*column) { |
||||
case 7: /* tcpConnectionState */ |
||||
value->u32 = pcb->state + 1; |
||||
break; |
||||
case 8: /* tcpConnectionProcess */ |
||||
value->u32 = 0; /* not supported */ |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip_addr_t local_ip, remote_ip; |
||||
u16_t local_port, remote_port; |
||||
struct tcp_pcb *pcb; |
||||
u8_t idx = 0; |
||||
u8_t i; |
||||
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ |
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); |
||||
if (idx == 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ |
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); |
||||
if (idx == 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* find tcp_pcb with requested ip and port*/ |
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { |
||||
pcb = *tcp_pcb_nonlisten_lists[i]; |
||||
|
||||
while (pcb != NULL) { |
||||
if (ip_addr_cmp(&local_ip, &pcb->local_ip) && |
||||
(local_port == pcb->local_port) && |
||||
ip_addr_cmp(&remote_ip, &pcb->remote_ip) && |
||||
(remote_port == pcb->remote_port)) { |
||||
/* fill in object properties */ |
||||
return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); |
||||
} |
||||
pcb = pcb->next; |
||||
} |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct tcp_pcb *pcb; |
||||
struct snmp_next_oid_state state; |
||||
/* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort
|
||||
* 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ |
||||
u32_t result_temp[38]; |
||||
u8_t i; |
||||
struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { |
||||
pcb = *tcp_pcb_nonlisten_lists[i]; |
||||
|
||||
while (pcb != NULL) { |
||||
u8_t idx = 0; |
||||
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; |
||||
|
||||
/* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ |
||||
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); |
||||
|
||||
/* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ |
||||
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, idx, pcb); |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); |
||||
} else { |
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
} |
||||
|
||||
/* --- tcpListenerTable --- */ |
||||
|
||||
static snmp_err_t
|
||||
tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) |
||||
{ |
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
switch (*column) { |
||||
case 4: /* tcpListenerProcess */ |
||||
value->u32 = 0; /* not supported */ |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip_addr_t local_ip; |
||||
u16_t local_port; |
||||
struct tcp_pcb_listen *pcb; |
||||
u8_t idx = 0; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ |
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); |
||||
if (idx == 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* find tcp_pcb with requested ip and port*/ |
||||
pcb = tcp_listen_pcbs.listen_pcbs; |
||||
while (pcb != NULL) { |
||||
if (ip_addr_cmp(&local_ip, &pcb->local_ip) && |
||||
(local_port == pcb->local_port)) { |
||||
/* fill in object properties */ |
||||
return tcp_ListenerTable_get_cell_value_core(column, value); |
||||
} |
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE;
|
||||
} |
||||
|
||||
static snmp_err_t |
||||
tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct tcp_pcb_listen *pcb; |
||||
struct snmp_next_oid_state state; |
||||
/* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ |
||||
u32_t result_temp[19]; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
pcb = tcp_listen_pcbs.listen_pcbs; |
||||
while (pcb != NULL) { |
||||
u8_t idx = 0; |
||||
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; |
||||
|
||||
/* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ |
||||
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, idx, NULL); |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return tcp_ListenerTable_get_cell_value_core(column, value); |
||||
} else { |
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
} |
||||
|
||||
static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); |
||||
static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); |
||||
|
||||
#if LWIP_IPV4 |
||||
static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ |
||||
{ 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ |
||||
{ 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ |
||||
{ 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ |
||||
{ 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); |
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { |
||||
/* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */
|
||||
{ 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ |
||||
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); |
||||
|
||||
|
||||
static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { |
||||
/* all items except tcpListenerProcess are declared as not-accessible */
|
||||
{ 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); |
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) |
||||
CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) |
||||
CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) |
||||
CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) |
||||
CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) |
||||
CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) |
||||
CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) |
||||
CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) |
||||
CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) |
||||
CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) |
||||
CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) |
||||
CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) |
||||
#if LWIP_IPV4 |
||||
CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) |
||||
#endif /* LWIP_IPV4 */ |
||||
CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) |
||||
CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) |
||||
CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) |
||||
CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) |
||||
CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) |
||||
CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) |
||||
|
||||
static const struct snmp_node* const tcp_nodes[] = { |
||||
&SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, |
||||
&SYNC_NODE_NAME(tcp_RtoMin).node.node, |
||||
&SYNC_NODE_NAME(tcp_RtoMax).node.node, |
||||
&SYNC_NODE_NAME(tcp_MaxConn).node.node, |
||||
&SYNC_NODE_NAME(tcp_ActiveOpens).node.node, |
||||
&SYNC_NODE_NAME(tcp_PassiveOpens).node.node, |
||||
&SYNC_NODE_NAME(tcp_AttemptFails).node.node, |
||||
&SYNC_NODE_NAME(tcp_EstabResets).node.node, |
||||
&SYNC_NODE_NAME(tcp_CurrEstab).node.node, |
||||
&SYNC_NODE_NAME(tcp_InSegs).node.node, |
||||
&SYNC_NODE_NAME(tcp_OutSegs).node.node, |
||||
&SYNC_NODE_NAME(tcp_RetransSegs).node.node, |
||||
#if LWIP_IPV4 |
||||
&SYNC_NODE_NAME(tcp_ConnTable).node.node, |
||||
#endif /* LWIP_IPV4 */ |
||||
&SYNC_NODE_NAME(tcp_InErrs).node.node, |
||||
&SYNC_NODE_NAME(tcp_OutRsts).node.node, |
||||
&SYNC_NODE_NAME(tcp_HCInSegs).node.node, |
||||
&SYNC_NODE_NAME(tcp_HCOutSegs).node.node, |
||||
&SYNC_NODE_NAME(tcp_ConnectionTable).node.node, |
||||
&SYNC_NODE_NAME(tcp_ListenerTable).node.node |
||||
}; |
||||
|
||||
const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); |
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ |
||||
@ -1,357 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Management Information Base II (RFC1213) UDP objects and functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
*/ |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_mib2.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/udp.h" |
||||
#include "lwip/stats.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP |
||||
|
||||
#if SNMP_USE_NETCONN |
||||
#define SYNC_NODE_NAME(node_name) node_name ## _synced |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ |
||||
static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); |
||||
#else |
||||
#define SYNC_NODE_NAME(node_name) node_name |
||||
#define CREATE_LWIP_SYNC_NODE(oid, node_name) |
||||
#endif |
||||
|
||||
/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ |
||||
|
||||
static s16_t
|
||||
udp_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
u32_t *uint_ptr = (u32_t*)value; |
||||
|
||||
switch (instance->node->oid) { |
||||
case 1: /* udpInDatagrams */ |
||||
*uint_ptr = STATS_GET(mib2.udpindatagrams); |
||||
return sizeof(*uint_ptr); |
||||
case 2: /* udpNoPorts */ |
||||
*uint_ptr = STATS_GET(mib2.udpnoports); |
||||
return sizeof(*uint_ptr); |
||||
case 3: /* udpInErrors */ |
||||
*uint_ptr = STATS_GET(mib2.udpinerrors); |
||||
return sizeof(*uint_ptr); |
||||
case 4: /* udpOutDatagrams */ |
||||
*uint_ptr = STATS_GET(mib2.udpoutdatagrams); |
||||
return sizeof(*uint_ptr); |
||||
case 8: /* udpHCInDatagrams */ |
||||
memset(value, 0, 2*sizeof(u32_t)); /* not supported */ |
||||
return 2*sizeof(u32_t); |
||||
case 9: /* udpHCOutDatagrams */ |
||||
memset(value, 0, 2*sizeof(u32_t)); /* not supported */ |
||||
return 2*sizeof(u32_t); |
||||
default: |
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); |
||||
break; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/* --- udpEndpointTable --- */ |
||||
|
||||
static snmp_err_t
|
||||
udp_endpointTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) |
||||
{ |
||||
/* all items except udpEndpointProcess are declared as not-accessible */
|
||||
switch (*column) { |
||||
case 8: /* udpEndpointProcess */ |
||||
value->u32 = 0; /* not supported */ |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
udp_endpointTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip_addr_t local_ip, remote_ip; |
||||
u16_t local_port, remote_port; |
||||
struct udp_pcb *pcb; |
||||
u8_t idx = 0; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ |
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); |
||||
if (idx == 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ |
||||
idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); |
||||
if (idx == 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* udpEndpointInstance */ |
||||
if (row_oid_len < (idx+1)) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
if (row_oid[idx] != 0) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* find udp_pcb with requested ip and port*/ |
||||
pcb = udp_pcbs; |
||||
while (pcb != NULL) { |
||||
if (ip_addr_cmp(&local_ip, &pcb->local_ip) && |
||||
(local_port == pcb->local_port) && |
||||
ip_addr_cmp(&remote_ip, &pcb->remote_ip) && |
||||
(remote_port == pcb->remote_port)) { |
||||
/* fill in object properties */ |
||||
return udp_endpointTable_get_cell_value_core(column, value); |
||||
} |
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
udp_endpointTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct udp_pcb *pcb; |
||||
struct snmp_next_oid_state state; |
||||
/* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort +
|
||||
* 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + |
||||
* 1x udpEndpointInstance = 39 |
||||
*/ |
||||
u32_t result_temp[39]; |
||||
|
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
pcb = udp_pcbs; |
||||
while (pcb != NULL) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; |
||||
u8_t idx = 0; |
||||
|
||||
/* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ |
||||
idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); |
||||
|
||||
/* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ |
||||
idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); |
||||
|
||||
test_oid[idx] = 0; /* udpEndpointInstance */
|
||||
idx++; |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, idx, NULL); |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return udp_endpointTable_get_cell_value_core(column, value); |
||||
} else { |
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
} |
||||
|
||||
/* --- udpTable --- */ |
||||
|
||||
#if LWIP_IPV4 |
||||
|
||||
/* list of allowed value ranges for incoming OID */ |
||||
static const struct snmp_oid_range udp_Table_oid_ranges[] = { |
||||
{ 0, 0xff }, /* IP A */ |
||||
{ 0, 0xff }, /* IP B */ |
||||
{ 0, 0xff }, /* IP C */ |
||||
{ 0, 0xff }, /* IP D */ |
||||
{ 1, 0xffff } /* Port */ |
||||
}; |
||||
|
||||
static snmp_err_t
|
||||
udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
LWIP_UNUSED_ARG(value_len); |
||||
|
||||
switch (*column) { |
||||
case 1: /* udpLocalAddress */ |
||||
/* set reference to PCB local IP and return a generic node that copies IP4 addresses */ |
||||
value->u32 = ip_2_ip4(&pcb->local_ip)->addr; |
||||
break; |
||||
case 2: /* udpLocalPort */ |
||||
/* set reference to PCB local port and return a generic node that copies u16_t values */ |
||||
value->u32 = pcb->local_port; |
||||
break; |
||||
default: |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
udp_Table_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
ip4_addr_t ip; |
||||
u16_t port; |
||||
struct udp_pcb *pcb; |
||||
|
||||
/* check if incoming OID length and if values are in plausible range */ |
||||
if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
/* get IP and port from incoming OID */ |
||||
snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ |
||||
port = (u16_t)row_oid[4]; |
||||
|
||||
/* find udp_pcb with requested ip and port*/ |
||||
pcb = udp_pcbs; |
||||
while (pcb != NULL) { |
||||
if (IP_IS_V4_VAL(pcb->local_ip)) { |
||||
if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { |
||||
/* fill in object properties */ |
||||
return udp_Table_get_cell_value_core(pcb, column, value, value_len); |
||||
} |
||||
} |
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
static snmp_err_t
|
||||
udp_Table_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) |
||||
{ |
||||
struct udp_pcb *pcb; |
||||
struct snmp_next_oid_state state; |
||||
u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; |
||||
|
||||
/* init struct to search next oid */ |
||||
snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); |
||||
|
||||
/* iterate over all possible OIDs to find the next one */ |
||||
pcb = udp_pcbs; |
||||
while (pcb != NULL) { |
||||
u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; |
||||
|
||||
if (IP_IS_V4_VAL(pcb->local_ip)) { |
||||
snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); |
||||
test_oid[4] = pcb->local_port; |
||||
|
||||
/* check generated OID: is it a candidate for the next one? */ |
||||
snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); |
||||
} |
||||
|
||||
pcb = pcb->next; |
||||
} |
||||
|
||||
/* did we find a next one? */ |
||||
if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { |
||||
snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); |
||||
/* fill in object properties */ |
||||
return udp_Table_get_cell_value_core((struct udp_pcb*)state.reference, column, value, value_len); |
||||
} else { |
||||
/* not found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
} |
||||
|
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); |
||||
static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); |
||||
static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); |
||||
static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); |
||||
static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); |
||||
static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); |
||||
|
||||
#if LWIP_IPV4 |
||||
static const struct snmp_table_simple_col_def udp_Table_columns[] = { |
||||
{ 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ |
||||
{ 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ |
||||
}; |
||||
static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); |
||||
#endif /* LWIP_IPV4 */ |
||||
|
||||
static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { |
||||
/* all items except udpEndpointProcess are declared as not-accessible */
|
||||
{ 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ |
||||
}; |
||||
|
||||
static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); |
||||
|
||||
/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */
|
||||
CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) |
||||
CREATE_LWIP_SYNC_NODE(2, udp_noPorts) |
||||
CREATE_LWIP_SYNC_NODE(3, udp_inErrors) |
||||
CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) |
||||
#if LWIP_IPV4 |
||||
CREATE_LWIP_SYNC_NODE(5, udp_Table) |
||||
#endif /* LWIP_IPV4 */ |
||||
CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) |
||||
CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) |
||||
CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) |
||||
|
||||
static const struct snmp_node* const udp_nodes[] = { |
||||
&SYNC_NODE_NAME(udp_inDatagrams).node.node, |
||||
&SYNC_NODE_NAME(udp_noPorts).node.node, |
||||
&SYNC_NODE_NAME(udp_inErrors).node.node, |
||||
&SYNC_NODE_NAME(udp_outDatagrams).node.node, |
||||
#if LWIP_IPV4 |
||||
&SYNC_NODE_NAME(udp_Table).node.node, |
||||
#endif /* LWIP_IPV4 */ |
||||
&SYNC_NODE_NAME(udp_endpointTable).node.node, |
||||
&SYNC_NODE_NAME(udp_HCInDatagrams).node.node, |
||||
&SYNC_NODE_NAME(udp_HCOutDatagrams).node.node |
||||
}; |
||||
|
||||
const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); |
||||
#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ |
||||
File diff suppressed because it is too large
Load Diff
@ -1,193 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP Agent message handling structures (internal API, do not use in client code). |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. |
||||
* Copyright (c) 2016 Elias Oenal. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv> |
||||
* Martin Hentschel <info@cl-soft.de> |
||||
* Elias Oenal <lwip@eliasoenal.com> |
||||
*/ |
||||
|
||||
#ifndef LWIP_HDR_APPS_SNMP_MSG_H |
||||
#define LWIP_HDR_APPS_SNMP_MSG_H |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP |
||||
|
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "snmp_pbuf_stream.h" |
||||
#include "lwip/ip_addr.h" |
||||
#include "lwip/err.h" |
||||
|
||||
#if LWIP_SNMP_V3 |
||||
#include "snmpv3_priv.h" |
||||
#endif |
||||
|
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* The listen port of the SNMP agent. Clients have to make their requests to
|
||||
this port. Most standard clients won't work if you change this! */ |
||||
#ifndef SNMP_IN_PORT |
||||
#define SNMP_IN_PORT 161 |
||||
#endif |
||||
/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't
|
||||
work if you change this! */ |
||||
#ifndef SNMP_TRAP_PORT |
||||
#define SNMP_TRAP_PORT 162 |
||||
#endif |
||||
|
||||
/* version defines used in PDU */ |
||||
#define SNMP_VERSION_1 0 |
||||
#define SNMP_VERSION_2c 1 |
||||
#define SNMP_VERSION_3 3 |
||||
|
||||
struct snmp_varbind_enumerator |
||||
{ |
||||
struct snmp_pbuf_stream pbuf_stream; |
||||
u16_t varbind_count; |
||||
}; |
||||
|
||||
typedef u8_t snmp_vb_enumerator_err_t; |
||||
#define SNMP_VB_ENUMERATOR_ERR_OK 0 |
||||
#define SNMP_VB_ENUMERATOR_ERR_EOVB 1 |
||||
#define SNMP_VB_ENUMERATOR_ERR_ASN1ERROR 2 |
||||
#define SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH 3 |
||||
|
||||
void snmp_vb_enumerator_init(struct snmp_varbind_enumerator* enumerator, struct pbuf* p, u16_t offset, u16_t length); |
||||
snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator* enumerator, struct snmp_varbind* varbind); |
||||
|
||||
struct snmp_request |
||||
{ |
||||
/* Communication handle */ |
||||
void *handle; |
||||
/* source IP address */ |
||||
const ip_addr_t *source_ip; |
||||
/* source UDP port */ |
||||
u16_t source_port; |
||||
/* incoming snmp version */ |
||||
u8_t version; |
||||
/* community name (zero terminated) */ |
||||
u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; |
||||
/* community string length (exclusive zero term) */ |
||||
u16_t community_strlen; |
||||
/* request type */ |
||||
u8_t request_type; |
||||
/* request ID */ |
||||
s32_t request_id; |
||||
/* error status */ |
||||
s32_t error_status; |
||||
/* error index */ |
||||
s32_t error_index; |
||||
/* non-repeaters (getBulkRequest (SNMPv2c)) */ |
||||
s32_t non_repeaters; |
||||
/* max-repetitions (getBulkRequest (SNMPv2c)) */ |
||||
s32_t max_repetitions; |
||||
|
||||
#if LWIP_SNMP_V3 |
||||
s32_t msg_id; |
||||
s32_t msg_max_size; |
||||
u8_t msg_flags; |
||||
s32_t msg_security_model; |
||||
u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; |
||||
u8_t msg_authoritative_engine_id_len; |
||||
s32_t msg_authoritative_engine_boots; |
||||
s32_t msg_authoritative_engine_time; |
||||
u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; |
||||
u8_t msg_user_name_len; |
||||
u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; |
||||
u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; |
||||
u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; |
||||
u8_t context_engine_id_len; |
||||
u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; |
||||
u8_t context_name_len; |
||||
#endif |
||||
|
||||
struct pbuf *inbound_pbuf; |
||||
struct snmp_varbind_enumerator inbound_varbind_enumerator; |
||||
u16_t inbound_varbind_offset; |
||||
u16_t inbound_varbind_len; |
||||
u16_t inbound_padding_len; |
||||
|
||||
struct pbuf *outbound_pbuf; |
||||
struct snmp_pbuf_stream outbound_pbuf_stream; |
||||
u16_t outbound_pdu_offset; |
||||
u16_t outbound_error_status_offset; |
||||
u16_t outbound_error_index_offset; |
||||
u16_t outbound_varbind_offset; |
||||
#if LWIP_SNMP_V3 |
||||
u16_t outbound_msg_global_data_offset; |
||||
u16_t outbound_msg_global_data_end; |
||||
u16_t outbound_msg_security_parameters_str_offset; |
||||
u16_t outbound_msg_security_parameters_seq_offset; |
||||
u16_t outbound_msg_security_parameters_end; |
||||
u16_t outbound_msg_authentication_parameters_offset; |
||||
u16_t outbound_scoped_pdu_seq_offset; |
||||
u16_t outbound_scoped_pdu_string_offset; |
||||
#endif |
||||
|
||||
u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; |
||||
}; |
||||
|
||||
/** A helper struct keeping length information about varbinds */ |
||||
struct snmp_varbind_len |
||||
{ |
||||
u8_t vb_len_len; |
||||
u16_t vb_value_len; |
||||
u8_t oid_len_len; |
||||
u16_t oid_value_len; |
||||
u8_t value_len_len; |
||||
u16_t value_value_len; |
||||
}; |
||||
|
||||
/** Agent community string */ |
||||
extern const char *snmp_community; |
||||
/** Agent community string for write access */ |
||||
extern const char *snmp_community_write; |
||||
/** handle for sending traps */ |
||||
extern void* snmp_traps_handle; |
||||
|
||||
void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); |
||||
err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); |
||||
u8_t snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result); |
||||
err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); |
||||
err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind* varbind); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
|
||||
#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ |
||||
@ -1,120 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP netconn frontend. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_USE_NETCONN |
||||
|
||||
#include "lwip/api.h" |
||||
#include "lwip/ip.h" |
||||
#include "lwip/udp.h" |
||||
#include "snmp_msg.h" |
||||
#include "lwip/sys.h" |
||||
|
||||
/** SNMP netconn API worker thread */ |
||||
static void |
||||
snmp_netconn_thread(void *arg) |
||||
{ |
||||
struct netconn *conn; |
||||
struct netbuf *buf; |
||||
err_t err; |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
/* Bind to SNMP port with default IP address */ |
||||
#if LWIP_IPV6 |
||||
conn = netconn_new(NETCONN_UDP_IPV6); |
||||
netconn_bind(conn, IP6_ADDR_ANY, SNMP_IN_PORT); |
||||
#else /* LWIP_IPV6 */ |
||||
conn = netconn_new(NETCONN_UDP); |
||||
netconn_bind(conn, IP_ADDR_ANY, SNMP_IN_PORT); |
||||
#endif /* LWIP_IPV6 */ |
||||
LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); |
||||
|
||||
snmp_traps_handle = conn; |
||||
|
||||
do { |
||||
err = netconn_recv(conn, &buf); |
||||
|
||||
if (err == ERR_OK) { |
||||
snmp_receive(conn, buf->p, &buf->addr, buf->port); |
||||
} |
||||
|
||||
if (buf != NULL) { |
||||
netbuf_delete(buf); |
||||
} |
||||
} while(1); |
||||
} |
||||
|
||||
err_t
|
||||
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) |
||||
{ |
||||
err_t result; |
||||
struct netbuf buf; |
||||
|
||||
memset(&buf, 0, sizeof(buf)); |
||||
buf.p = p; |
||||
result = netconn_sendto((struct netconn*)handle, &buf, dst, port); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
u8_t |
||||
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) |
||||
{ |
||||
struct netconn* conn = (struct netconn*)handle; |
||||
struct netif *dst_if; |
||||
const ip_addr_t* dst_ip; |
||||
|
||||
LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ |
||||
|
||||
ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); |
||||
|
||||
if ((dst_if != NULL) && (dst_ip != NULL)) { |
||||
ip_addr_copy(*result, *dst_ip); |
||||
return 1; |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Starts SNMP Agent. |
||||
*/ |
||||
void |
||||
snmp_init(void) |
||||
{ |
||||
sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ |
||||
@ -1,156 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP pbuf stream wrapper implementation (internal API, do not use in client code). |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel <info@cl-soft.de> |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "snmp_pbuf_stream.h" |
||||
#include "lwip/def.h" |
||||
#include <string.h> |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length) |
||||
{ |
||||
pbuf_stream->offset = offset; |
||||
pbuf_stream->length = length; |
||||
pbuf_stream->pbuf = p; |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data) |
||||
{ |
||||
if (pbuf_stream->length == 0) { |
||||
return ERR_BUF; |
||||
} |
||||
|
||||
if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { |
||||
return ERR_BUF; |
||||
} |
||||
|
||||
pbuf_stream->offset++; |
||||
pbuf_stream->length--; |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data) |
||||
{ |
||||
return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len) |
||||
{ |
||||
if (pbuf_stream->length < buf_len) { |
||||
return ERR_BUF; |
||||
} |
||||
|
||||
if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { |
||||
return ERR_BUF; |
||||
} |
||||
|
||||
pbuf_stream->offset += buf_len; |
||||
pbuf_stream->length -= buf_len; |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len) |
||||
{ |
||||
|
||||
if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { |
||||
return ERR_ARG; |
||||
} |
||||
if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
if (len == 0) { |
||||
len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); |
||||
} |
||||
|
||||
while (len > 0) { |
||||
u16_t chunk_len; |
||||
err_t err; |
||||
u16_t target_offset; |
||||
struct pbuf* pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); |
||||
|
||||
if ((pbuf == NULL) || (pbuf->len == 0)) { |
||||
return ERR_BUF; |
||||
} |
||||
|
||||
chunk_len = LWIP_MIN(len, pbuf->len); |
||||
err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t*)pbuf->payload)[target_offset], chunk_len); |
||||
if (err != ERR_OK) { |
||||
return err; |
||||
} |
||||
|
||||
pbuf_stream->offset += chunk_len; |
||||
pbuf_stream->length -= chunk_len; |
||||
len -= chunk_len; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset) |
||||
{ |
||||
if ((offset < 0) || (offset > pbuf_stream->length)) { |
||||
/* we cannot seek backwards or forward behind stream end */ |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
pbuf_stream->offset += (u16_t)offset; |
||||
pbuf_stream->length -= (u16_t)offset; |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
err_t |
||||
snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset) |
||||
{ |
||||
s32_t rel_offset = offset - pbuf_stream->offset; |
||||
return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,73 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP pbuf stream wrapper (internal API, do not use in client code). |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel <info@cl-soft.de> |
||||
* |
||||
*/ |
||||
|
||||
#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H |
||||
#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP |
||||
|
||||
#include "lwip/err.h" |
||||
#include "lwip/pbuf.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct snmp_pbuf_stream |
||||
{ |
||||
struct pbuf* pbuf; |
||||
u16_t offset; |
||||
u16_t length; |
||||
}; |
||||
|
||||
err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream* pbuf_stream, struct pbuf* p, u16_t offset, u16_t length); |
||||
err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream* pbuf_stream, u8_t* data); |
||||
err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream* pbuf_stream, u8_t data); |
||||
err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream* pbuf_stream, const void* buf, u16_t buf_len); |
||||
err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream* pbuf_stream, struct snmp_pbuf_stream* target_pbuf_stream, u16_t len); |
||||
err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream* pbuf_stream, s32_t offset); |
||||
err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream* pbuf_stream, u32_t offset); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
|
||||
#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ |
||||
@ -1,100 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP RAW API frontend. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
#include "lwip/ip_addr.h" |
||||
|
||||
#if LWIP_SNMP && SNMP_USE_RAW |
||||
|
||||
#include "lwip/udp.h" |
||||
#include "lwip/ip.h" |
||||
#include "snmp_msg.h" |
||||
|
||||
/* lwIP UDP receive callback function */ |
||||
static void |
||||
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) |
||||
{ |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
snmp_receive(pcb, p, addr, port); |
||||
|
||||
pbuf_free(p); |
||||
} |
||||
|
||||
err_t
|
||||
snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) |
||||
{ |
||||
return udp_sendto((struct udp_pcb*)handle, p, dst, port); |
||||
} |
||||
|
||||
u8_t |
||||
snmp_get_local_ip_for_dst(void* handle, const ip_addr_t *dst, ip_addr_t *result) |
||||
{ |
||||
struct udp_pcb* udp_pcb = (struct udp_pcb*)handle; |
||||
struct netif *dst_if; |
||||
const ip_addr_t* dst_ip; |
||||
|
||||
LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ |
||||
|
||||
ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); |
||||
|
||||
if ((dst_if != NULL) && (dst_ip != NULL)) { |
||||
ip_addr_copy(*result, *dst_ip); |
||||
return 1; |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_core |
||||
* Starts SNMP Agent. |
||||
* Allocates UDP pcb and binds it to IP_ADDR_ANY port 161. |
||||
*/ |
||||
void |
||||
snmp_init(void) |
||||
{ |
||||
err_t err; |
||||
|
||||
struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); |
||||
LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); |
||||
|
||||
snmp_traps_handle = snmp_pcb; |
||||
|
||||
udp_recv(snmp_pcb, snmp_recv, (void *)SNMP_IN_PORT); |
||||
err = udp_bind(snmp_pcb, IP_ANY_TYPE, SNMP_IN_PORT); |
||||
LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP && SNMP_USE_RAW */ |
||||
@ -1,220 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP scalar node support implementation. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel <info@cl-soft.de> |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "lwip/apps/snmp_scalar.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
|
||||
static s16_t snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value); |
||||
static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value); |
||||
static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value); |
||||
|
||||
snmp_err_t
|
||||
snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
const struct snmp_scalar_node* scalar_node = (const struct snmp_scalar_node*)(const void*)instance->node; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
/* scalar only has one dedicated instance: .0 */ |
||||
if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
instance->access = scalar_node->access; |
||||
instance->asn1_type = scalar_node->asn1_type; |
||||
instance->get_value = scalar_node->get_value; |
||||
instance->set_test = scalar_node->set_test; |
||||
instance->set_value = scalar_node->set_value; |
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
snmp_err_t
|
||||
snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
/* because our only instance is .0 we can only return a next instance if no instance oid is passed */ |
||||
if (instance->instance_oid.len == 0) { |
||||
instance->instance_oid.len = 1; |
||||
instance->instance_oid.id[0] = 0; |
||||
|
||||
return snmp_scalar_get_instance(root_oid, root_oid_len, instance); |
||||
} |
||||
|
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
|
||||
snmp_err_t |
||||
snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { |
||||
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; |
||||
const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; |
||||
u32_t i = 0; |
||||
|
||||
while (i < array_node->array_node_count) { |
||||
if (array_node_def->oid == instance->instance_oid.id[0]) { |
||||
break; |
||||
} |
||||
|
||||
array_node_def++; |
||||
i++; |
||||
} |
||||
|
||||
if (i < array_node->array_node_count) { |
||||
instance->access = array_node_def->access; |
||||
instance->asn1_type = array_node_def->asn1_type; |
||||
instance->get_value = snmp_scalar_array_get_value; |
||||
instance->set_test = snmp_scalar_array_set_test; |
||||
instance->set_value = snmp_scalar_array_set_value; |
||||
instance->reference.const_ptr = array_node_def; |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
} |
||||
|
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
snmp_err_t |
||||
snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; |
||||
const struct snmp_scalar_array_node_def* array_node_def = array_node->array_nodes; |
||||
const struct snmp_scalar_array_node_def* result = NULL; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { |
||||
/* return node with lowest OID */ |
||||
u16_t i = 0; |
||||
|
||||
result = array_node_def; |
||||
array_node_def++; |
||||
|
||||
for (i = 1; i < array_node->array_node_count; i++) { |
||||
if (array_node_def->oid < result->oid) { |
||||
result = array_node_def; |
||||
} |
||||
array_node_def++; |
||||
} |
||||
} else if (instance->instance_oid.len >= 1) { |
||||
if (instance->instance_oid.len == 1) { |
||||
/* if we have the requested OID we return its instance, otherwise we search for the next available */
|
||||
u16_t i = 0; |
||||
while (i < array_node->array_node_count) { |
||||
if (array_node_def->oid == instance->instance_oid.id[0]) { |
||||
result = array_node_def; |
||||
break; |
||||
} |
||||
|
||||
array_node_def++; |
||||
i++; |
||||
} |
||||
} |
||||
if (result == NULL) { |
||||
u32_t oid_dist = 0xFFFFFFFFUL; |
||||
u16_t i = 0; |
||||
array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ |
||||
while (i < array_node->array_node_count) { |
||||
if ((array_node_def->oid > instance->instance_oid.id[0]) && |
||||
((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { |
||||
result = array_node_def; |
||||
oid_dist = array_node_def->oid - instance->instance_oid.id[0]; |
||||
} |
||||
|
||||
array_node_def++; |
||||
i++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (result == NULL) { |
||||
/* nothing to return */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
instance->instance_oid.len = 2; |
||||
instance->instance_oid.id[0] = result->oid; |
||||
instance->instance_oid.id[1] = 0; |
||||
|
||||
instance->access = result->access; |
||||
instance->asn1_type = result->asn1_type; |
||||
instance->get_value = snmp_scalar_array_get_value; |
||||
instance->set_test = snmp_scalar_array_set_test; |
||||
instance->set_value = snmp_scalar_array_set_value; |
||||
instance->reference.const_ptr = result; |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
static s16_t |
||||
snmp_scalar_array_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; |
||||
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; |
||||
|
||||
return array_node->get_value(array_node_def, value); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
snmp_scalar_array_set_test(struct snmp_node_instance* instance, u16_t value_len, void* value) |
||||
{ |
||||
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; |
||||
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; |
||||
|
||||
return array_node->set_test(array_node_def, value_len, value); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
snmp_scalar_array_set_value(struct snmp_node_instance* instance, u16_t value_len, void* value) |
||||
{ |
||||
const struct snmp_scalar_array_node* array_node = (const struct snmp_scalar_array_node*)(const void*)instance->node; |
||||
const struct snmp_scalar_array_node_def* array_node_def = (const struct snmp_scalar_array_node_def*)instance->reference.const_ptr; |
||||
|
||||
return array_node->set_value(array_node_def, value_len, value); |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,343 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP table support implementation. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel <info@cl-soft.de> |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/apps/snmp_table.h" |
||||
#include <string.h> |
||||
|
||||
snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; |
||||
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ |
||||
/* fixed row entry always has oid 1 */ |
||||
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { |
||||
/* search column */ |
||||
const struct snmp_table_col_def* col_def = table_node->columns; |
||||
u16_t i = table_node->column_count; |
||||
while (i > 0) { |
||||
if (col_def->index == instance->instance_oid.id[1]) { |
||||
break; |
||||
} |
||||
|
||||
col_def++; |
||||
i--; |
||||
} |
||||
|
||||
if (i > 0) { |
||||
/* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ |
||||
instance->asn1_type = col_def->asn1_type; |
||||
instance->access = col_def->access; |
||||
instance->get_value = table_node->get_value; |
||||
instance->set_test = table_node->set_test; |
||||
instance->set_value = table_node->set_value; |
||||
|
||||
ret = table_node->get_cell_instance( |
||||
&(instance->instance_oid.id[1]), |
||||
&(instance->instance_oid.id[2]), |
||||
instance->instance_oid.len-2, |
||||
instance); |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
const struct snmp_table_node* table_node = (const struct snmp_table_node*)(const void*)instance->node; |
||||
const struct snmp_table_col_def* col_def; |
||||
struct snmp_obj_id row_oid; |
||||
u32_t column = 0; |
||||
snmp_err_t result; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
/* check that first part of id is 0 or 1, referencing fixed row entry */ |
||||
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
if (instance->instance_oid.len > 1) { |
||||
column = instance->instance_oid.id[1]; |
||||
} |
||||
if (instance->instance_oid.len > 2) { |
||||
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); |
||||
} else { |
||||
row_oid.len = 0; |
||||
} |
||||
|
||||
instance->get_value = table_node->get_value; |
||||
instance->set_test = table_node->set_test; |
||||
instance->set_value = table_node->set_value; |
||||
|
||||
/* resolve column and value */ |
||||
do { |
||||
u16_t i; |
||||
const struct snmp_table_col_def* next_col_def = NULL; |
||||
col_def = table_node->columns; |
||||
|
||||
for (i = 0; i < table_node->column_count; i++) { |
||||
if (col_def->index == column) { |
||||
next_col_def = col_def; |
||||
break; |
||||
} else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { |
||||
next_col_def = col_def; |
||||
} |
||||
col_def++; |
||||
} |
||||
|
||||
if (next_col_def == NULL) { |
||||
/* no further column found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
instance->asn1_type = next_col_def->asn1_type; |
||||
instance->access = next_col_def->access; |
||||
|
||||
result = table_node->get_next_cell_instance( |
||||
&next_col_def->index, |
||||
&row_oid, |
||||
instance); |
||||
|
||||
if (result == SNMP_ERR_NOERROR) { |
||||
col_def = next_col_def; |
||||
break; |
||||
} |
||||
|
||||
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ |
||||
column = next_col_def->index + 1; |
||||
} while (1); |
||||
|
||||
/* build resulting oid */ |
||||
instance->instance_oid.len = 2; |
||||
instance->instance_oid.id[0] = 1; |
||||
instance->instance_oid.id[1] = col_def->index; |
||||
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
|
||||
snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; |
||||
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
/* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ |
||||
/* fixed row entry always has oid 1 */ |
||||
if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { |
||||
ret = table_node->get_cell_value( |
||||
&(instance->instance_oid.id[1]), |
||||
&(instance->instance_oid.id[2]), |
||||
instance->instance_oid.len-2, |
||||
&instance->reference, |
||||
&instance->reference_len); |
||||
|
||||
if (ret == SNMP_ERR_NOERROR) { |
||||
/* search column */ |
||||
const struct snmp_table_simple_col_def* col_def = table_node->columns; |
||||
u32_t i = table_node->column_count; |
||||
while (i > 0) { |
||||
if (col_def->index == instance->instance_oid.id[1]) { |
||||
break; |
||||
} |
||||
|
||||
col_def++; |
||||
i--; |
||||
} |
||||
|
||||
if (i > 0) { |
||||
instance->asn1_type = col_def->asn1_type; |
||||
instance->access = SNMP_NODE_INSTANCE_READ_ONLY; |
||||
instance->set_test = NULL; |
||||
instance->set_value = NULL; |
||||
|
||||
switch (col_def->data_type) { |
||||
case SNMP_VARIANT_VALUE_TYPE_U32: |
||||
instance->get_value = snmp_table_extract_value_from_u32ref; |
||||
break; |
||||
case SNMP_VARIANT_VALUE_TYPE_S32: |
||||
instance->get_value = snmp_table_extract_value_from_s32ref; |
||||
break; |
||||
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ |
||||
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: |
||||
instance->get_value = snmp_table_extract_value_from_refconstptr; |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); |
||||
return SNMP_ERR_GENERROR; |
||||
}
|
||||
|
||||
ret = SNMP_ERR_NOERROR; |
||||
} else { |
||||
ret = SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
}
|
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
const struct snmp_table_simple_node* table_node = (const struct snmp_table_simple_node*)(const void*)instance->node; |
||||
const struct snmp_table_simple_col_def* col_def; |
||||
struct snmp_obj_id row_oid; |
||||
u32_t column = 0; |
||||
snmp_err_t result; |
||||
|
||||
LWIP_UNUSED_ARG(root_oid); |
||||
LWIP_UNUSED_ARG(root_oid_len); |
||||
|
||||
/* check that first part of id is 0 or 1, referencing fixed row entry */ |
||||
if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
if (instance->instance_oid.len > 1) { |
||||
column = instance->instance_oid.id[1]; |
||||
} |
||||
if (instance->instance_oid.len > 2) { |
||||
snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); |
||||
} else { |
||||
row_oid.len = 0; |
||||
} |
||||
|
||||
/* resolve column and value */ |
||||
do { |
||||
u32_t i; |
||||
const struct snmp_table_simple_col_def* next_col_def = NULL; |
||||
col_def = table_node->columns; |
||||
|
||||
for (i = 0; i < table_node->column_count; i++) { |
||||
if (col_def->index == column) { |
||||
next_col_def = col_def; |
||||
break; |
||||
} else if ((col_def->index > column) && ((next_col_def == NULL) || |
||||
(col_def->index < next_col_def->index))) { |
||||
next_col_def = col_def; |
||||
} |
||||
col_def++; |
||||
} |
||||
|
||||
if (next_col_def == NULL) { |
||||
/* no further column found */ |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
result = table_node->get_next_cell_instance_and_value( |
||||
&next_col_def->index, |
||||
&row_oid, |
||||
&instance->reference, |
||||
&instance->reference_len); |
||||
|
||||
if (result == SNMP_ERR_NOERROR) { |
||||
col_def = next_col_def; |
||||
break; |
||||
} |
||||
|
||||
row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ |
||||
column = next_col_def->index + 1; |
||||
} |
||||
while (1); |
||||
|
||||
instance->asn1_type = col_def->asn1_type; |
||||
instance->access = SNMP_NODE_INSTANCE_READ_ONLY; |
||||
instance->set_test = NULL; |
||||
instance->set_value = NULL; |
||||
|
||||
switch (col_def->data_type) { |
||||
case SNMP_VARIANT_VALUE_TYPE_U32: |
||||
instance->get_value = snmp_table_extract_value_from_u32ref; |
||||
break; |
||||
case SNMP_VARIANT_VALUE_TYPE_S32: |
||||
instance->get_value = snmp_table_extract_value_from_s32ref; |
||||
break; |
||||
case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ |
||||
case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: |
||||
instance->get_value = snmp_table_extract_value_from_refconstptr; |
||||
break; |
||||
default: |
||||
LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); |
||||
return SNMP_ERR_GENERROR; |
||||
} |
||||
|
||||
/* build resulting oid */ |
||||
instance->instance_oid.len = 2; |
||||
instance->instance_oid.id[0] = 1; |
||||
instance->instance_oid.id[1] = col_def->index; |
||||
snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); |
||||
|
||||
return SNMP_ERR_NOERROR; |
||||
} |
||||
|
||||
|
||||
s16_t |
||||
snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
s32_t *dst = (s32_t*)value; |
||||
*dst = instance->reference.s32; |
||||
return sizeof(*dst); |
||||
} |
||||
|
||||
s16_t |
||||
snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
u32_t *dst = (u32_t*)value; |
||||
*dst = instance->reference.u32; |
||||
return sizeof(*dst); |
||||
} |
||||
|
||||
s16_t |
||||
snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
MEMCPY(value, instance->reference.const_ptr, instance->reference_len); |
||||
return (u16_t)instance->reference_len; |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,218 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMP thread synchronization implementation. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Dirk Ziegelmeier <dziegel@gmx.de> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include "lwip/apps/snmp_threadsync.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "lwip/sys.h" |
||||
#include <string.h> |
||||
|
||||
static void |
||||
call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) |
||||
{ |
||||
sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); |
||||
call_data->threadsync_node->instance->sync_fn(fn, call_data); |
||||
sys_sem_wait(&call_data->threadsync_node->instance->sem); |
||||
sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); |
||||
} |
||||
|
||||
static void |
||||
threadsync_get_value_synced(void *ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
|
||||
call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static s16_t |
||||
threadsync_get_value(struct snmp_node_instance* instance, void* value) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; |
||||
|
||||
call_data->arg1.value = value; |
||||
call_synced_function(call_data, threadsync_get_value_synced); |
||||
|
||||
return call_data->retval.s16; |
||||
} |
||||
|
||||
static void |
||||
threadsync_set_test_synced(void *ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
|
||||
call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; |
||||
|
||||
call_data->arg1.value = value; |
||||
call_data->arg2.len = len; |
||||
call_synced_function(call_data, threadsync_set_test_synced); |
||||
|
||||
return call_data->retval.err; |
||||
} |
||||
|
||||
static void |
||||
threadsync_set_value_synced(void *ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
|
||||
call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; |
||||
|
||||
call_data->arg1.value = value; |
||||
call_data->arg2.len = len; |
||||
call_synced_function(call_data, threadsync_set_value_synced); |
||||
|
||||
return call_data->retval.err; |
||||
} |
||||
|
||||
static void |
||||
threadsync_release_instance_synced(void* ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
|
||||
call_data->proxy_instance.release_instance(&call_data->proxy_instance); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static void |
||||
threadsync_release_instance(struct snmp_node_instance *instance) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr; |
||||
|
||||
if (call_data->proxy_instance.release_instance != NULL) { |
||||
call_synced_function(call_data, threadsync_release_instance_synced); |
||||
} |
||||
} |
||||
|
||||
static void |
||||
get_instance_synced(void* ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; |
||||
|
||||
call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static void |
||||
get_next_instance_synced(void* ctx) |
||||
{ |
||||
struct threadsync_data *call_data = (struct threadsync_data*)ctx; |
||||
const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node; |
||||
|
||||
call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); |
||||
|
||||
sys_sem_signal(&call_data->threadsync_node->instance->sem); |
||||
} |
||||
|
||||
static snmp_err_t |
||||
do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn) |
||||
{ |
||||
const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node; |
||||
struct threadsync_data *call_data = &threadsync_node->instance->data; |
||||
|
||||
if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { |
||||
LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); |
||||
return SNMP_ERR_NOSUCHINSTANCE; |
||||
} |
||||
|
||||
memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); |
||||
|
||||
instance->reference.ptr = call_data; |
||||
snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); |
||||
|
||||
call_data->proxy_instance.node = &threadsync_node->target->node; |
||||
call_data->threadsync_node = threadsync_node; |
||||
|
||||
call_data->arg1.root_oid = root_oid; |
||||
call_data->arg2.root_oid_len = root_oid_len; |
||||
call_synced_function(call_data, fn); |
||||
|
||||
if (call_data->retval.err == SNMP_ERR_NOERROR) { |
||||
instance->access = call_data->proxy_instance.access; |
||||
instance->asn1_type = call_data->proxy_instance.asn1_type; |
||||
instance->release_instance = threadsync_release_instance; |
||||
instance->get_value = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL; |
||||
instance->set_value = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL; |
||||
instance->set_test = (call_data->proxy_instance.set_test != NULL)? threadsync_set_test : NULL; |
||||
snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); |
||||
} |
||||
|
||||
return call_data->retval.err; |
||||
} |
||||
|
||||
snmp_err_t |
||||
snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
return do_sync(root_oid, root_oid_len, instance, get_instance_synced); |
||||
} |
||||
|
||||
snmp_err_t |
||||
snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance) |
||||
{ |
||||
return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); |
||||
} |
||||
|
||||
/** Initializes thread synchronization instance */ |
||||
void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) |
||||
{ |
||||
err_t err = sys_mutex_new(&instance->sem_usage_mutex); |
||||
LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); |
||||
err = sys_sem_new(&instance->sem, 0); |
||||
LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); |
||||
instance->sync_fn = sync_fn; |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,443 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMPv1 traps implementation. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Martin Hentschel |
||||
* Christiaan Simons <christiaan.simons@axon.tv> |
||||
* |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "lwip/snmp.h" |
||||
#include "lwip/sys.h" |
||||
#include "lwip/apps/snmp.h" |
||||
#include "lwip/apps/snmp_core.h" |
||||
#include "snmp_msg.h" |
||||
#include "snmp_asn1.h" |
||||
#include "snmp_core_priv.h" |
||||
|
||||
struct snmp_msg_trap |
||||
{ |
||||
/* source enterprise ID (sysObjectID) */ |
||||
const struct snmp_obj_id *enterprise; |
||||
/* source IP address, raw network order format */ |
||||
ip_addr_t sip; |
||||
/* generic trap code */ |
||||
u32_t gen_trap; |
||||
/* specific trap code */ |
||||
u32_t spc_trap; |
||||
/* timestamp */ |
||||
u32_t ts; |
||||
/* snmp_version */ |
||||
u32_t snmp_version; |
||||
|
||||
/* output trap lengths used in ASN encoding */ |
||||
/* encoding pdu length */ |
||||
u16_t pdulen; |
||||
/* encoding community length */ |
||||
u16_t comlen; |
||||
/* encoding sequence length */ |
||||
u16_t seqlen; |
||||
/* encoding varbinds sequence length */ |
||||
u16_t vbseqlen; |
||||
}; |
||||
|
||||
static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); |
||||
static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); |
||||
static void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); |
||||
static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); |
||||
|
||||
/** Agent community string for sending traps */ |
||||
extern const char *snmp_community_trap; |
||||
|
||||
void* snmp_traps_handle; |
||||
|
||||
struct snmp_trap_dst |
||||
{ |
||||
/* destination IP address in network order */ |
||||
ip_addr_t dip; |
||||
/* set to 0 when disabled, >0 when enabled */ |
||||
u8_t enable; |
||||
}; |
||||
static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; |
||||
|
||||
static u8_t snmp_auth_traps_enabled = 0; |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Sets enable switch for this trap destination. |
||||
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 |
||||
* @param enable switch if 0 destination is disabled >0 enabled. |
||||
*/ |
||||
void |
||||
snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) |
||||
{ |
||||
if (dst_idx < SNMP_TRAP_DESTINATIONS) { |
||||
trap_dst[dst_idx].enable = enable; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Sets IPv4 address for this trap destination. |
||||
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 |
||||
* @param dst IPv4 address in host order. |
||||
*/ |
||||
void |
||||
snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) |
||||
{ |
||||
if (dst_idx < SNMP_TRAP_DESTINATIONS) { |
||||
ip_addr_set(&trap_dst[dst_idx].dip, dst); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Enable/disable authentication traps |
||||
*/ |
||||
void |
||||
snmp_set_auth_traps_enabled(u8_t enable) |
||||
{ |
||||
snmp_auth_traps_enabled = enable; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Get authentication traps enabled state |
||||
*/ |
||||
u8_t |
||||
snmp_get_auth_traps_enabled(void) |
||||
{ |
||||
return snmp_auth_traps_enabled; |
||||
} |
||||
|
||||
|
||||
/**
|
||||
* Sends an generic or enterprise specific trap message. |
||||
* |
||||
* @param generic_trap is the trap code |
||||
* @param eoid points to enterprise object identifier |
||||
* @param specific_trap used for enterprise traps when generic_trap == 6 |
||||
* @return ERR_OK when success, ERR_MEM if we're out of memory |
||||
* |
||||
* @note the use of the enterprise identifier field |
||||
* is per RFC1215. |
||||
* Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps |
||||
* and .iso.org.dod.internet.private.enterprises.yourenterprise |
||||
* (sysObjectID) for specific traps. |
||||
*/ |
||||
static err_t |
||||
snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) |
||||
{ |
||||
struct snmp_msg_trap trap_msg; |
||||
struct snmp_trap_dst *td; |
||||
struct pbuf *p; |
||||
u16_t i, tot_len; |
||||
err_t err = ERR_OK; |
||||
|
||||
trap_msg.snmp_version = 0; |
||||
|
||||
for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { |
||||
if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { |
||||
/* lookup current source address for this dst */ |
||||
if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { |
||||
if (device_enterprise_oid == NULL) { |
||||
trap_msg.enterprise = snmp_get_device_enterprise_oid(); |
||||
} else { |
||||
trap_msg.enterprise = device_enterprise_oid; |
||||
} |
||||
|
||||
trap_msg.gen_trap = generic_trap; |
||||
if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { |
||||
trap_msg.spc_trap = specific_trap; |
||||
} else { |
||||
trap_msg.spc_trap = 0; |
||||
} |
||||
|
||||
MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); |
||||
|
||||
/* pass 0, calculate length fields */ |
||||
tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); |
||||
tot_len = snmp_trap_header_sum(&trap_msg, tot_len); |
||||
|
||||
/* allocate pbuf(s) */ |
||||
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); |
||||
if (p != NULL) { |
||||
struct snmp_pbuf_stream pbuf_stream; |
||||
snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); |
||||
|
||||
/* pass 1, encode packet ino the pbuf(s) */ |
||||
snmp_trap_header_enc(&trap_msg, &pbuf_stream); |
||||
snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); |
||||
|
||||
snmp_stats.outtraps++; |
||||
snmp_stats.outpkts++; |
||||
|
||||
/** send to the TRAP destination */ |
||||
snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); |
||||
pbuf_free(p); |
||||
} else { |
||||
err = ERR_MEM; |
||||
} |
||||
} else { |
||||
/* routing error */ |
||||
err = ERR_RTE; |
||||
} |
||||
} |
||||
} |
||||
return err; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Send generic SNMP trap |
||||
*/ |
||||
err_t
|
||||
snmp_send_trap_generic(s32_t generic_trap) |
||||
{ |
||||
static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; |
||||
return snmp_send_trap(&oid, generic_trap, 0, NULL); |
||||
} |
||||
|
||||
/**
|
||||
*@ingroup snmp_traps |
||||
* Send specific SNMP trap with variable bindings |
||||
*/ |
||||
err_t |
||||
snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) |
||||
{ |
||||
return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Send coldstart trap |
||||
*/ |
||||
void |
||||
snmp_coldstart_trap(void) |
||||
{ |
||||
snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup snmp_traps |
||||
* Send authentication failure trap (used internally by agent)
|
||||
*/ |
||||
void |
||||
snmp_authfail_trap(void) |
||||
{ |
||||
if (snmp_auth_traps_enabled != 0) { |
||||
snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); |
||||
} |
||||
} |
||||
|
||||
static u16_t |
||||
snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) |
||||
{ |
||||
struct snmp_varbind *varbind; |
||||
u16_t tot_len; |
||||
u8_t tot_len_len; |
||||
|
||||
tot_len = 0; |
||||
varbind = varbinds; |
||||
while (varbind != NULL) { |
||||
struct snmp_varbind_len len; |
||||
|
||||
if (snmp_varbind_length(varbind, &len) == ERR_OK) { |
||||
tot_len += 1 + len.vb_len_len + len.vb_value_len; |
||||
} |
||||
|
||||
varbind = varbind->next; |
||||
} |
||||
|
||||
trap->vbseqlen = tot_len; |
||||
snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); |
||||
tot_len += 1 + tot_len_len; |
||||
|
||||
return tot_len; |
||||
} |
||||
|
||||
/**
|
||||
* Sums trap header field lengths from tail to head and |
||||
* returns trap_header_lengths for second encoding pass. |
||||
* |
||||
* @param vb_len varbind-list length |
||||
* @param thl points to returned header lengths |
||||
* @return the required length for encoding the trap header |
||||
*/ |
||||
static u16_t |
||||
snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) |
||||
{ |
||||
u16_t tot_len; |
||||
u16_t len; |
||||
u8_t lenlen; |
||||
|
||||
tot_len = vb_len; |
||||
|
||||
snmp_asn1_enc_u32t_cnt(trap->ts, &len); |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
if (IP_IS_V6_VAL(trap->sip)) { |
||||
#if LWIP_IPV6 |
||||
len = sizeof(ip_2_ip6(&trap->sip)->addr); |
||||
#endif |
||||
} else { |
||||
#if LWIP_IPV4 |
||||
len = sizeof(ip_2_ip4(&trap->sip)->addr); |
||||
#endif |
||||
} |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
trap->pdulen = tot_len; |
||||
snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); |
||||
tot_len += 1 + lenlen; |
||||
|
||||
trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); |
||||
snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); |
||||
tot_len += 1 + lenlen + trap->comlen; |
||||
|
||||
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); |
||||
snmp_asn1_enc_length_cnt(len, &lenlen); |
||||
tot_len += 1 + len + lenlen; |
||||
|
||||
trap->seqlen = tot_len; |
||||
snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); |
||||
tot_len += 1 + lenlen; |
||||
|
||||
return tot_len; |
||||
} |
||||
|
||||
static void |
||||
snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) |
||||
{ |
||||
struct snmp_asn1_tlv tlv; |
||||
struct snmp_varbind *varbind; |
||||
|
||||
varbind = varbinds; |
||||
|
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
|
||||
while (varbind != NULL) { |
||||
snmp_append_outbound_varbind(pbuf_stream, varbind); |
||||
|
||||
varbind = varbind->next; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Encodes trap header from head to tail. |
||||
*/ |
||||
static void |
||||
snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) |
||||
{ |
||||
struct snmp_asn1_tlv tlv; |
||||
|
||||
/* 'Message' sequence */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
|
||||
/* version */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); |
||||
snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); |
||||
|
||||
/* community */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); |
||||
|
||||
/* 'PDU' sequence */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
|
||||
/* object ID */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); |
||||
snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); |
||||
|
||||
/* IP addr */ |
||||
if (IP_IS_V6_VAL(trap->sip)) { |
||||
#if LWIP_IPV6 |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); |
||||
#endif |
||||
} else { |
||||
#if LWIP_IPV4 |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); |
||||
#endif |
||||
} |
||||
|
||||
/* trap length */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); |
||||
snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); |
||||
|
||||
/* specific trap */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); |
||||
snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); |
||||
|
||||
/* timestamp */ |
||||
SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); |
||||
snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); |
||||
snmp_ans1_enc_tlv(pbuf_stream, &tlv); |
||||
snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP */ |
||||
@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Additional SNMPv3 functionality RFC3414 and RFC3826. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Elias Oenal. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Elias Oenal <lwip@eliasoenal.com> |
||||
*/ |
||||
|
||||
#include "snmpv3_priv.h" |
||||
#include "lwip/apps/snmpv3.h" |
||||
#include "lwip/sys.h" |
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && LWIP_SNMP_V3 |
||||
|
||||
#ifdef LWIP_SNMPV3_INCLUDE_ENGINE |
||||
#include LWIP_SNMPV3_INCLUDE_ENGINE |
||||
#endif |
||||
|
||||
#define SNMP_MAX_TIME_BOOT 2147483647UL |
||||
|
||||
/** Call this if engine has been changed. Has to reset boots, see below */ |
||||
void |
||||
snmpv3_engine_id_changed(void) |
||||
{ |
||||
snmpv3_set_engine_boots(0); |
||||
} |
||||
|
||||
/** According to RFC3414 2.2.2.
|
||||
* |
||||
* The number of times that the SNMP engine has |
||||
* (re-)initialized itself since snmpEngineID |
||||
* was last configured. |
||||
*/ |
||||
u32_t |
||||
snmpv3_get_engine_boots_internal(void) |
||||
{ |
||||
if (snmpv3_get_engine_boots() == 0 || |
||||
snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { |
||||
return snmpv3_get_engine_boots(); |
||||
} |
||||
|
||||
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); |
||||
return snmpv3_get_engine_boots(); |
||||
} |
||||
|
||||
/** RFC3414 2.2.2.
|
||||
* |
||||
* Once the timer reaches 2147483647 it gets reset to zero and the |
||||
* engine boot ups get incremented. |
||||
*/ |
||||
u32_t |
||||
snmpv3_get_engine_time_internal(void) |
||||
{ |
||||
if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { |
||||
snmpv3_reset_engine_time(); |
||||
|
||||
if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { |
||||
snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); |
||||
} else { |
||||
snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); |
||||
} |
||||
} |
||||
|
||||
return snmpv3_get_engine_time(); |
||||
} |
||||
|
||||
#if LWIP_SNMP_V3_CRYPTO |
||||
|
||||
/* This function ignores the byte order suggestion in RFC3414
|
||||
* since it simply doesn't influence the effectiveness of an IV. |
||||
* |
||||
* Implementing RFC3826 priv param algorithm if LWIP_RAND is available. |
||||
* |
||||
* @todo: This is a potential thread safety issue. |
||||
*/ |
||||
err_t |
||||
snmpv3_build_priv_param(u8_t* priv_param) |
||||
{ |
||||
#ifdef LWIP_RAND /* Based on RFC3826 */ |
||||
static u8_t init; |
||||
static u32_t priv1, priv2; |
||||
|
||||
/* Lazy initialisation */ |
||||
if (init == 0) { |
||||
init = 1; |
||||
priv1 = LWIP_RAND(); |
||||
priv2 = LWIP_RAND(); |
||||
} |
||||
|
||||
memcpy(&priv_param[0], &priv1, sizeof(priv1)); |
||||
memcpy(&priv_param[4], &priv2, sizeof(priv2)); |
||||
|
||||
/* Emulate 64bit increment */ |
||||
priv1++; |
||||
if (!priv1) { /* Overflow */ |
||||
priv2++; |
||||
} |
||||
#else /* Based on RFC3414 */ |
||||
static u32_t ctr; |
||||
u32_t boots = LWIP_SNMPV3_GET_ENGINE_BOOTS(); |
||||
memcpy(&priv_param[0], &boots, 4); |
||||
memcpy(&priv_param[4], &ctr, 4); |
||||
ctr++; |
||||
#endif |
||||
return ERR_OK; |
||||
} |
||||
#endif /* LWIP_SNMP_V3_CRYPTO */ |
||||
|
||||
#endif |
||||
@ -1,145 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Dummy SNMPv3 functions. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Elias Oenal. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Elias Oenal <lwip@eliasoenal.com> |
||||
* Dirk Ziegelmeier <dirk@ziegelmeier.net> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmpv3.h" |
||||
#include "snmpv3_priv.h" |
||||
#include <string.h> |
||||
#include "lwip/err.h" |
||||
|
||||
#if LWIP_SNMP && LWIP_SNMP_V3 |
||||
|
||||
/**
|
||||
* @param username is a pointer to a string. |
||||
* @param auth_algo is a pointer to u8_t. The implementation has to set this if user was found. |
||||
* @param auth_key is a pointer to a pointer to a string. Implementation has to set this if user was found. |
||||
* @param priv_algo is a pointer to u8_t. The implementation has to set this if user was found. |
||||
* @param priv_key is a pointer to a pointer to a string. Implementation has to set this if user was found. |
||||
*/ |
||||
err_t |
||||
snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key) |
||||
{ |
||||
const char* engine_id; |
||||
u8_t engine_id_len; |
||||
|
||||
if(strlen(username) == 0) { |
||||
return ERR_OK; |
||||
} |
||||
|
||||
if(memcmp(username, "lwip", 4) != 0) { |
||||
return ERR_VAL; |
||||
} |
||||
|
||||
snmpv3_get_engine_id(&engine_id, &engine_id_len); |
||||
|
||||
if(auth_key != NULL) { |
||||
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, |
||||
(const u8_t*)engine_id, engine_id_len, |
||||
auth_key); |
||||
*auth_algo = SNMP_V3_AUTH_ALGO_SHA; |
||||
} |
||||
if(priv_key != NULL) { |
||||
snmpv3_password_to_key_sha((const u8_t*)"maplesyrup", 10, |
||||
(const u8_t*)engine_id, engine_id_len, |
||||
priv_key); |
||||
*priv_algo = SNMP_V3_PRIV_ALGO_DES; |
||||
} |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Get engine ID from persistence |
||||
* @param id |
||||
* @param len |
||||
*/ |
||||
void |
||||
snmpv3_get_engine_id(const char **id, u8_t *len) |
||||
{ |
||||
*id = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"; |
||||
*len = 12; |
||||
} |
||||
|
||||
/**
|
||||
* Store engine ID in persistence |
||||
* @param id |
||||
* @param len |
||||
*/ |
||||
err_t |
||||
snmpv3_set_engine_id(const char *id, u8_t len) |
||||
{ |
||||
LWIP_UNUSED_ARG(id); |
||||
LWIP_UNUSED_ARG(len); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
/**
|
||||
* Get engine boots from persistence. Must be increased on each boot. |
||||
* @return
|
||||
*/ |
||||
u32_t |
||||
snmpv3_get_engine_boots(void) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* Store engine boots in persistence |
||||
* @param boots |
||||
*/ |
||||
void
|
||||
snmpv3_set_engine_boots(u32_t boots) |
||||
{ |
||||
LWIP_UNUSED_ARG(boots); |
||||
} |
||||
|
||||
/**
|
||||
* RFC3414 2.2.2. |
||||
* Once the timer reaches 2147483647 it gets reset to zero and the |
||||
* engine boot ups get incremented. |
||||
*/ |
||||
u32_t |
||||
snmpv3_get_engine_time(void) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
/**
|
||||
* Reset current engine time to 0 |
||||
*/ |
||||
void |
||||
snmpv3_reset_engine_time(void) |
||||
{ |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP && LWIP_SNMP_V3 */ |
||||
@ -1,331 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNMPv3 crypto/auth functions implemented for ARM mbedtls. |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Elias Oenal <lwip@eliasoenal.com> |
||||
* Dirk Ziegelmeier <dirk@ziegelmeier.net> |
||||
*/ |
||||
|
||||
#include "lwip/apps/snmpv3.h" |
||||
#include "snmpv3_priv.h" |
||||
#include "lwip/arch.h" |
||||
#include "snmp_msg.h" |
||||
#include "lwip/sys.h" |
||||
#include <string.h> |
||||
|
||||
#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS |
||||
|
||||
#include "mbedtls/md.h" |
||||
#include "mbedtls/cipher.h" |
||||
|
||||
#include "mbedtls/md5.h" |
||||
#include "mbedtls/sha1.h" |
||||
|
||||
err_t |
||||
snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, |
||||
const u8_t* key, u8_t algo, u8_t* hmac_out) |
||||
{ |
||||
u32_t i; |
||||
u8_t key_len; |
||||
const mbedtls_md_info_t *md_info; |
||||
mbedtls_md_context_t ctx; |
||||
struct snmp_pbuf_stream read_stream; |
||||
snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); |
||||
|
||||
if (algo == SNMP_V3_AUTH_ALGO_MD5) { |
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); |
||||
key_len = SNMP_V3_MD5_LEN; |
||||
} else if (algo == SNMP_V3_AUTH_ALGO_SHA) { |
||||
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); |
||||
key_len = SNMP_V3_SHA_LEN; |
||||
} else { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
mbedtls_md_init(&ctx); |
||||
if(mbedtls_md_setup(&ctx, md_info, 1) != 0) { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { |
||||
goto free_md; |
||||
} |
||||
|
||||
for (i = 0; i < length; i++) { |
||||
u8_t byte; |
||||
|
||||
if (snmp_pbuf_stream_read(&read_stream, &byte)) { |
||||
goto free_md; |
||||
} |
||||
|
||||
if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { |
||||
goto free_md; |
||||
} |
||||
} |
||||
|
||||
if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { |
||||
goto free_md; |
||||
} |
||||
|
||||
mbedtls_md_free(&ctx); |
||||
return ERR_OK; |
||||
|
||||
free_md: |
||||
mbedtls_md_free(&ctx); |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
#if LWIP_SNMP_V3_CRYPTO |
||||
|
||||
err_t |
||||
snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, |
||||
const u8_t* key, const u8_t* priv_param, const u32_t engine_boots, |
||||
const u32_t engine_time, u8_t algo, u8_t mode) |
||||
{ |
||||
size_t i; |
||||
mbedtls_cipher_context_t ctx; |
||||
const mbedtls_cipher_info_t *cipher_info; |
||||
|
||||
struct snmp_pbuf_stream read_stream; |
||||
struct snmp_pbuf_stream write_stream; |
||||
snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); |
||||
snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); |
||||
mbedtls_cipher_init(&ctx); |
||||
|
||||
if (algo == SNMP_V3_PRIV_ALGO_DES) { |
||||
u8_t iv_local[8]; |
||||
u8_t out_bytes[8]; |
||||
size_t out_len; |
||||
|
||||
/* RFC 3414 mandates padding for DES */ |
||||
if ((length & 0x07) != 0) { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); |
||||
if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { |
||||
return ERR_ARG; |
||||
} |
||||
if(mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { |
||||
return ERR_ARG; |
||||
} |
||||
if(mbedtls_cipher_setkey(&ctx, key, 8*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { |
||||
goto error; |
||||
} |
||||
|
||||
/* Prepare IV */
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { |
||||
iv_local[i] = priv_param[i] ^ key[i + 8]; |
||||
} |
||||
if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { |
||||
goto error; |
||||
} |
||||
|
||||
for (i = 0; i < length; i += 8) { |
||||
size_t j; |
||||
u8_t in_bytes[8]; |
||||
out_len = LWIP_ARRAYSIZE(out_bytes) ; |
||||
|
||||
for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { |
||||
snmp_pbuf_stream_read(&read_stream, &in_bytes[j]); |
||||
} |
||||
|
||||
if(mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { |
||||
goto error; |
||||
} |
||||
|
||||
snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); |
||||
} |
||||
|
||||
out_len = LWIP_ARRAYSIZE(out_bytes); |
||||
if(mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { |
||||
goto error; |
||||
} |
||||
snmp_pbuf_stream_writebuf(&write_stream, out_bytes, out_len); |
||||
} else if (algo == SNMP_V3_PRIV_ALGO_AES) { |
||||
u8_t iv_local[16]; |
||||
|
||||
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); |
||||
if(mbedtls_cipher_setup(&ctx, cipher_info) != 0) { |
||||
return ERR_ARG; |
||||
} |
||||
if(mbedtls_cipher_setkey(&ctx, key, 16*8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT)? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { |
||||
goto error; |
||||
} |
||||
|
||||
/*
|
||||
* IV is the big endian concatenation of boots, |
||||
* uptime and priv param - see RFC3826. |
||||
*/ |
||||
iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; |
||||
iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; |
||||
iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; |
||||
iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; |
||||
iv_local[4 + 0] = (engine_time >> 24) & 0xFF; |
||||
iv_local[4 + 1] = (engine_time >> 16) & 0xFF; |
||||
iv_local[4 + 2] = (engine_time >> 8) & 0xFF; |
||||
iv_local[4 + 3] = (engine_time >> 0) & 0xFF; |
||||
memcpy(iv_local + 8, priv_param, 8); |
||||
if(mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { |
||||
goto error; |
||||
} |
||||
|
||||
for (i = 0; i < length; i++) { |
||||
u8_t in_byte; |
||||
u8_t out_byte; |
||||
size_t out_len = sizeof(out_byte); |
||||
|
||||
snmp_pbuf_stream_read(&read_stream, &in_byte); |
||||
if(mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { |
||||
goto error; |
||||
} |
||||
snmp_pbuf_stream_write(&write_stream, out_byte); |
||||
} |
||||
} else { |
||||
return ERR_ARG; |
||||
} |
||||
|
||||
mbedtls_cipher_free(&ctx); |
||||
return ERR_OK; |
||||
|
||||
error: |
||||
mbedtls_cipher_free(&ctx); |
||||
return ERR_OK; |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP_V3_CRYPTO */ |
||||
|
||||
/* A.2.1. Password to Key Sample Code for MD5 */ |
||||
void
|
||||
snmpv3_password_to_key_md5( |
||||
const u8_t *password, /* IN */ |
||||
u8_t passwordlen, /* IN */ |
||||
const u8_t *engineID, /* IN - pointer to snmpEngineID */ |
||||
u8_t engineLength,/* IN - length of snmpEngineID */ |
||||
u8_t *key) /* OUT - pointer to caller 16-octet buffer */ |
||||
{ |
||||
mbedtls_md5_context MD; |
||||
u8_t *cp, password_buf[64]; |
||||
u32_t password_index = 0; |
||||
u8_t i; |
||||
u32_t count = 0; |
||||
|
||||
mbedtls_md5_init(&MD); /* initialize MD5 */ |
||||
mbedtls_md5_starts(&MD); |
||||
|
||||
/**********************************************/ |
||||
/* Use while loop until we've done 1 Megabyte */ |
||||
/**********************************************/ |
||||
while (count < 1048576) { |
||||
cp = password_buf; |
||||
for (i = 0; i < 64; i++) { |
||||
/*************************************************/ |
||||
/* Take the next octet of the password, wrapping */ |
||||
/* to the beginning of the password as necessary.*/ |
||||
/*************************************************/ |
||||
*cp++ = password[password_index++ % passwordlen]; |
||||
} |
||||
mbedtls_md5_update(&MD, password_buf, 64); |
||||
count += 64; |
||||
} |
||||
mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ |
||||
|
||||
/*****************************************************/ |
||||
/* Now localize the key with the engineID and pass */ |
||||
/* through MD5 to produce final key */ |
||||
/* May want to ensure that engineLength <= 32, */ |
||||
/* otherwise need to use a buffer larger than 64 */ |
||||
/*****************************************************/ |
||||
memcpy(password_buf, key, 16); |
||||
memcpy(password_buf + 16, engineID, engineLength); |
||||
memcpy(password_buf + 16 + engineLength, key, 16); |
||||
|
||||
mbedtls_md5_starts(&MD); |
||||
mbedtls_md5_update(&MD, password_buf, 32 + engineLength); |
||||
mbedtls_md5_finish(&MD, key); |
||||
|
||||
mbedtls_md5_free(&MD); |
||||
return; |
||||
} |
||||
|
||||
/* A.2.2. Password to Key Sample Code for SHA */ |
||||
void
|
||||
snmpv3_password_to_key_sha( |
||||
const u8_t *password, /* IN */ |
||||
u8_t passwordlen, /* IN */ |
||||
const u8_t *engineID, /* IN - pointer to snmpEngineID */ |
||||
u8_t engineLength,/* IN - length of snmpEngineID */ |
||||
u8_t *key) /* OUT - pointer to caller 20-octet buffer */ |
||||
{ |
||||
mbedtls_sha1_context SH; |
||||
u8_t *cp, password_buf[72]; |
||||
u32_t password_index = 0; |
||||
u8_t i; |
||||
u32_t count = 0; |
||||
|
||||
mbedtls_sha1_init(&SH); /* initialize SHA */ |
||||
mbedtls_sha1_starts(&SH); |
||||
|
||||
/**********************************************/ |
||||
/* Use while loop until we've done 1 Megabyte */ |
||||
/**********************************************/ |
||||
while (count < 1048576) { |
||||
cp = password_buf; |
||||
for (i = 0; i < 64; i++) { |
||||
/*************************************************/ |
||||
/* Take the next octet of the password, wrapping */ |
||||
/* to the beginning of the password as necessary.*/ |
||||
/*************************************************/ |
||||
*cp++ = password[password_index++ % passwordlen]; |
||||
} |
||||
mbedtls_sha1_update(&SH, password_buf, 64); |
||||
count += 64; |
||||
} |
||||
mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ |
||||
|
||||
/*****************************************************/ |
||||
/* Now localize the key with the engineID and pass */ |
||||
/* through SHA to produce final key */ |
||||
/* May want to ensure that engineLength <= 32, */ |
||||
/* otherwise need to use a buffer larger than 72 */ |
||||
/*****************************************************/ |
||||
memcpy(password_buf, key, 20); |
||||
memcpy(password_buf + 20, engineID, engineLength); |
||||
memcpy(password_buf + 20 + engineLength, key, 20); |
||||
|
||||
mbedtls_sha1_starts(&SH); |
||||
mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); |
||||
mbedtls_sha1_finish(&SH, key); |
||||
|
||||
mbedtls_sha1_free(&SH); |
||||
return; |
||||
} |
||||
|
||||
#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ |
||||
@ -1,66 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Elias Oenal. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* Author: Elias Oenal <lwip@eliasoenal.com> |
||||
*/ |
||||
|
||||
#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H |
||||
#define LWIP_HDR_APPS_SNMP_V3_PRIV_H |
||||
|
||||
#include "lwip/apps/snmp_opts.h" |
||||
|
||||
#if LWIP_SNMP && LWIP_SNMP_V3 |
||||
|
||||
#include "snmp_pbuf_stream.h" |
||||
|
||||
/* According to RFC 3411 */ |
||||
#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 |
||||
#define SNMP_V3_MAX_USER_LENGTH 32 |
||||
|
||||
#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 |
||||
#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 |
||||
|
||||
#define SNMP_V3_AUTH_FLAG 0x01 |
||||
#define SNMP_V3_PRIV_FLAG 0x02 |
||||
|
||||
#define SNMP_V3_MD5_LEN 16 |
||||
#define SNMP_V3_SHA_LEN 20 |
||||
|
||||
u32_t snmpv3_get_engine_boots_internal(void); |
||||
u32_t snmpv3_get_engine_time_internal(void); |
||||
err_t snmpv3_auth(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, u8_t algo, u8_t* hmac_out); |
||||
err_t snmpv3_crypt(struct snmp_pbuf_stream* stream, u16_t length, const u8_t* key, |
||||
const u8_t* priv_param, const u32_t engine_boots, const u32_t engine_time, u8_t algo, u8_t mode); |
||||
err_t snmpv3_build_priv_param(u8_t* priv_param); |
||||
|
||||
#endif |
||||
|
||||
#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ |
||||
@ -1,726 +0,0 @@
|
||||
/**
|
||||
* @file |
||||
* SNTP client module |
||||
*/ |
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without modification, |
||||
* are permitted provided that the following conditions are met: |
||||
* |
||||
* 1. Redistributions of source code must retain the above copyright notice, |
||||
* this list of conditions and the following disclaimer. |
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* 3. The name of the author may not be used to endorse or promote products |
||||
* derived from this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
||||
* OF SUCH DAMAGE. |
||||
* |
||||
* This file is part of the lwIP TCP/IP stack. |
||||
* |
||||
* Author: Frédéric Bernon, Simon Goldschmidt |
||||
*/ |
||||
|
||||
|
||||
/**
|
||||
* @defgroup sntp SNTP |
||||
* @ingroup apps |
||||
* |
||||
* This is simple "SNTP" client for the lwIP raw API. |
||||
* It is a minimal implementation of SNTPv4 as specified in RFC 4330. |
||||
* |
||||
* For a list of some public NTP servers, see this link : |
||||
* http://support.ntp.org/bin/view/Servers/NTPPoolServers
|
||||
* |
||||
* @todo: |
||||
* - set/change servers at runtime |
||||
* - complete SNTP_CHECK_RESPONSE checks 3 and 4 |
||||
*/ |
||||
|
||||
#include "lwip/apps/sntp.h" |
||||
|
||||
#include "lwip/opt.h" |
||||
#include "lwip/timeouts.h" |
||||
#include "lwip/udp.h" |
||||
#include "lwip/dns.h" |
||||
#include "lwip/ip_addr.h" |
||||
#include "lwip/pbuf.h" |
||||
#include "lwip/dhcp.h" |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#if LWIP_UDP |
||||
|
||||
/* Handle support for more than one server via SNTP_MAX_SERVERS */ |
||||
#if SNTP_MAX_SERVERS > 1 |
||||
#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 |
||||
#else /* NTP_MAX_SERVERS > 1 */ |
||||
#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 |
||||
#endif /* NTP_MAX_SERVERS > 1 */ |
||||
|
||||
#if (SNTP_UPDATE_DELAY < 15000) && !defined(SNTP_SUPPRESS_DELAY_CHECK) |
||||
#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" |
||||
#endif |
||||
|
||||
/* Configure behaviour depending on microsecond or second precision */ |
||||
#ifdef SNTP_SET_SYSTEM_TIME_US |
||||
#define SNTP_CALC_TIME_US 1 |
||||
#define SNTP_RECEIVE_TIME_SIZE 2 |
||||
#else |
||||
#define SNTP_SET_SYSTEM_TIME_US(sec, us) |
||||
#define SNTP_CALC_TIME_US 0 |
||||
#define SNTP_RECEIVE_TIME_SIZE 1 |
||||
#endif |
||||
|
||||
|
||||
/* the various debug levels for this file */ |
||||
#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) |
||||
#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) |
||||
#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) |
||||
#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) |
||||
#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) |
||||
|
||||
#define SNTP_ERR_KOD 1 |
||||
|
||||
/* SNTP protocol defines */ |
||||
#define SNTP_MSG_LEN 48 |
||||
|
||||
#define SNTP_OFFSET_LI_VN_MODE 0 |
||||
#define SNTP_LI_MASK 0xC0 |
||||
#define SNTP_LI_NO_WARNING 0x00 |
||||
#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 |
||||
#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 |
||||
#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ |
||||
|
||||
#define SNTP_VERSION_MASK 0x38 |
||||
#define SNTP_VERSION (4/* NTP Version 4*/<<3) |
||||
|
||||
#define SNTP_MODE_MASK 0x07 |
||||
#define SNTP_MODE_CLIENT 0x03 |
||||
#define SNTP_MODE_SERVER 0x04 |
||||
#define SNTP_MODE_BROADCAST 0x05 |
||||
|
||||
#define SNTP_OFFSET_STRATUM 1 |
||||
#define SNTP_STRATUM_KOD 0x00 |
||||
|
||||
#define SNTP_OFFSET_ORIGINATE_TIME 24 |
||||
#define SNTP_OFFSET_RECEIVE_TIME 32 |
||||
#define SNTP_OFFSET_TRANSMIT_TIME 40 |
||||
|
||||
/* number of seconds between 1900 and 1970 (MSB=1)*/ |
||||
#define DIFF_SEC_1900_1970 (2208988800UL) |
||||
/* number of seconds between 1970 and Feb 7, 2036 (6:28:16 UTC) (MSB=0) */ |
||||
#define DIFF_SEC_1970_2036 (2085978496UL) |
||||
|
||||
/**
|
||||
* SNTP packet format (without optional fields) |
||||
* Timestamps are coded as 64 bits: |
||||
* - 32 bits seconds since Jan 01, 1970, 00:00 |
||||
* - 32 bits seconds fraction (0-padded) |
||||
* For future use, if the MSB in the seconds part is set, seconds are based |
||||
* on Feb 07, 2036, 06:28:16. |
||||
*/ |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/bpstruct.h" |
||||
#endif |
||||
PACK_STRUCT_BEGIN |
||||
struct sntp_msg { |
||||
PACK_STRUCT_FLD_8(u8_t li_vn_mode); |
||||
PACK_STRUCT_FLD_8(u8_t stratum); |
||||
PACK_STRUCT_FLD_8(u8_t poll); |
||||
PACK_STRUCT_FLD_8(u8_t precision); |
||||
PACK_STRUCT_FIELD(u32_t root_delay); |
||||
PACK_STRUCT_FIELD(u32_t root_dispersion); |
||||
PACK_STRUCT_FIELD(u32_t reference_identifier); |
||||
PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); |
||||
PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); |
||||
PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); |
||||
PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); |
||||
} PACK_STRUCT_STRUCT; |
||||
PACK_STRUCT_END |
||||
#ifdef PACK_STRUCT_USE_INCLUDES |
||||
# include "arch/epstruct.h" |
||||
#endif |
||||
|
||||
/* function prototypes */ |
||||
static void sntp_request(void *arg); |
||||
|
||||
/** The operating mode */ |
||||
static u8_t sntp_opmode; |
||||
|
||||
/** The UDP pcb used by the SNTP client */ |
||||
static struct udp_pcb* sntp_pcb; |
||||
/** Names/Addresses of servers */ |
||||
struct sntp_server { |
||||
#if SNTP_SERVER_DNS |
||||
char* name; |
||||
#endif /* SNTP_SERVER_DNS */ |
||||
ip_addr_t addr; |
||||
}; |
||||
static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; |
||||
|
||||
#if SNTP_GET_SERVERS_FROM_DHCP |
||||
static u8_t sntp_set_servers_from_dhcp; |
||||
#endif /* SNTP_GET_SERVERS_FROM_DHCP */ |
||||
#if SNTP_SUPPORT_MULTIPLE_SERVERS |
||||
/** The currently used server (initialized to 0) */ |
||||
static u8_t sntp_current_server; |
||||
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ |
||||
#define sntp_current_server 0 |
||||
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ |
||||
|
||||
#if SNTP_RETRY_TIMEOUT_EXP |
||||
#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT |
||||
/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ |
||||
static u32_t sntp_retry_timeout; |
||||
#else /* SNTP_RETRY_TIMEOUT_EXP */ |
||||
#define SNTP_RESET_RETRY_TIMEOUT() |
||||
#define sntp_retry_timeout SNTP_RETRY_TIMEOUT |
||||
#endif /* SNTP_RETRY_TIMEOUT_EXP */ |
||||
|
||||
#if SNTP_CHECK_RESPONSE >= 1 |
||||
/** Saves the last server address to compare with response */ |
||||
static ip_addr_t sntp_last_server_address; |
||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */ |
||||
|
||||
#if SNTP_CHECK_RESPONSE >= 2 |
||||
/** Saves the last timestamp sent (which is sent back by the server)
|
||||
* to compare against in response */ |
||||
static u32_t sntp_last_timestamp_sent[2]; |
||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */ |
||||
|
||||
/**
|
||||
* SNTP processing of received timestamp |
||||
*/ |
||||
static void |
||||
sntp_process(u32_t *receive_timestamp) |
||||
{ |
||||
/* convert SNTP time (1900-based) to unix GMT time (1970-based)
|
||||
* if MSB is 0, SNTP time is 2036-based! |
||||
*/ |
||||
u32_t rx_secs = ntohl(receive_timestamp[0]); |
||||
int is_1900_based = ((rx_secs & 0x80000000) != 0); |
||||
u32_t t = is_1900_based ? (rx_secs - DIFF_SEC_1900_1970) : (rx_secs + DIFF_SEC_1970_2036); |
||||
time_t tim = t; |
||||
|
||||
#if SNTP_CALC_TIME_US |
||||
u32_t us = ntohl(receive_timestamp[1]) / 4295; |
||||
SNTP_SET_SYSTEM_TIME_US(t, us); |
||||
/* display local time from GMT time */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&tim), us)); |
||||
|
||||
#else /* SNTP_CALC_TIME_US */ |
||||
|
||||
/* change system time and/or the update the RTC clock */ |
||||
SNTP_SET_SYSTEM_TIME(t); |
||||
/* display local time from GMT time */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&tim))); |
||||
#endif /* SNTP_CALC_TIME_US */ |
||||
LWIP_UNUSED_ARG(tim); |
||||
} |
||||
|
||||
/**
|
||||
* Initialize request struct to be sent to server. |
||||
*/ |
||||
static void |
||||
sntp_initialize_request(struct sntp_msg *req) |
||||
{ |
||||
memset(req, 0, SNTP_MSG_LEN); |
||||
req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; |
||||
|
||||
#if SNTP_CHECK_RESPONSE >= 2 |
||||
{ |
||||
u32_t sntp_time_sec, sntp_time_us; |
||||
/* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ |
||||
SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); |
||||
sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970); |
||||
req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; |
||||
/* we send/save us instead of fraction to be faster... */ |
||||
sntp_last_timestamp_sent[1] = htonl(sntp_time_us); |
||||
req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; |
||||
} |
||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */ |
||||
} |
||||
|
||||
/**
|
||||
* Retry: send a new request (and increase retry timeout). |
||||
* |
||||
* @param arg is unused (only necessary to conform to sys_timeout) |
||||
*/ |
||||
static void |
||||
sntp_retry(void* arg) |
||||
{ |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", |
||||
sntp_retry_timeout)); |
||||
|
||||
/* set up a timer to send a retry and increase the retry delay */ |
||||
sys_timeout(sntp_retry_timeout, sntp_request, NULL); |
||||
|
||||
#if SNTP_RETRY_TIMEOUT_EXP |
||||
{ |
||||
u32_t new_retry_timeout; |
||||
/* increase the timeout for next retry */ |
||||
new_retry_timeout = sntp_retry_timeout << 1; |
||||
/* limit to maximum timeout and prevent overflow */ |
||||
if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && |
||||
(new_retry_timeout > sntp_retry_timeout)) { |
||||
sntp_retry_timeout = new_retry_timeout; |
||||
} |
||||
} |
||||
#endif /* SNTP_RETRY_TIMEOUT_EXP */ |
||||
} |
||||
|
||||
#if SNTP_SUPPORT_MULTIPLE_SERVERS |
||||
/**
|
||||
* If Kiss-of-Death is received (or another packet parsing error), |
||||
* try the next server or retry the current server and increase the retry |
||||
* timeout if only one server is available. |
||||
* (implicitly, SNTP_MAX_SERVERS > 1) |
||||
* |
||||
* @param arg is unused (only necessary to conform to sys_timeout) |
||||
*/ |
||||
static void |
||||
sntp_try_next_server(void* arg) |
||||
{ |
||||
u8_t old_server, i; |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
old_server = sntp_current_server; |
||||
for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { |
||||
sntp_current_server++; |
||||
if (sntp_current_server >= SNTP_MAX_SERVERS) { |
||||
sntp_current_server = 0; |
||||
} |
||||
if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) |
||||
#if SNTP_SERVER_DNS |
||||
|| (sntp_servers[sntp_current_server].name != NULL) |
||||
#endif |
||||
) { |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", |
||||
(u16_t)sntp_current_server)); |
||||
/* new server: reset retry timeout */ |
||||
SNTP_RESET_RETRY_TIMEOUT(); |
||||
/* instantly send a request to the next server */ |
||||
sntp_request(NULL); |
||||
return; |
||||
} |
||||
} |
||||
/* no other valid server found */ |
||||
sntp_current_server = old_server; |
||||
sntp_retry(NULL); |
||||
} |
||||
#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ |
||||
/* Always retry on error if only one server is supported */ |
||||
#define sntp_try_next_server sntp_retry |
||||
#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ |
||||
|
||||
/** UDP recv callback for the sntp pcb */ |
||||
static void |
||||
sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) |
||||
{ |
||||
u8_t mode; |
||||
u8_t stratum; |
||||
u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; |
||||
err_t err; |
||||
|
||||
LWIP_UNUSED_ARG(arg); |
||||
LWIP_UNUSED_ARG(pcb); |
||||
|
||||
/* packet received: stop retry timeout */ |
||||
sys_untimeout(sntp_try_next_server, NULL); |
||||
sys_untimeout(sntp_request, NULL); |
||||
|
||||
err = ERR_ARG; |
||||
#if SNTP_CHECK_RESPONSE >= 1 |
||||
/* check server address and port */ |
||||
if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && |
||||
(port == SNTP_PORT)) |
||||
#else /* SNTP_CHECK_RESPONSE >= 1 */ |
||||
LWIP_UNUSED_ARG(addr); |
||||
LWIP_UNUSED_ARG(port); |
||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */ |
||||
{ |
||||
/* process the response */ |
||||
if (p->tot_len == SNTP_MSG_LEN) { |
||||
pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); |
||||
mode &= SNTP_MODE_MASK; |
||||
/* if this is a SNTP response... */ |
||||
if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || |
||||
((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { |
||||
pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); |
||||
if (stratum == SNTP_STRATUM_KOD) { |
||||
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ |
||||
err = SNTP_ERR_KOD; |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); |
||||
} else { |
||||
#if SNTP_CHECK_RESPONSE >= 2 |
||||
/* check originate_timetamp against sntp_last_timestamp_sent */ |
||||
u32_t originate_timestamp[2]; |
||||
pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); |
||||
if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || |
||||
(originate_timestamp[1] != sntp_last_timestamp_sent[1])) |
||||
{ |
||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); |
||||
} else |
||||
#endif /* SNTP_CHECK_RESPONSE >= 2 */ |
||||
/* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ |
||||
{ |
||||
/* correct answer */ |
||||
err = ERR_OK; |
||||
pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_TRANSMIT_TIME); |
||||
} |
||||
} |
||||
} else { |
||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); |
||||
/* wait for correct response */ |
||||
err = ERR_TIMEOUT; |
||||
} |
||||
} else { |
||||
LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); |
||||
} |
||||
} |
||||
#if SNTP_CHECK_RESPONSE >= 1 |
||||
else { |
||||
/* packet from wrong remote address or port, wait for correct response */ |
||||
err = ERR_TIMEOUT; |
||||
} |
||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */ |
||||
pbuf_free(p); |
||||
if (err == ERR_OK) { |
||||
sntp_process(receive_timestamp); |
||||
|
||||
/* Set up timeout for next request (only if poll response was received)*/ |
||||
if (sntp_opmode == SNTP_OPMODE_POLL) { |
||||
/* Correct response, reset retry timeout */ |
||||
SNTP_RESET_RETRY_TIMEOUT(); |
||||
|
||||
sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", |
||||
(u32_t)SNTP_UPDATE_DELAY)); |
||||
} |
||||
} else if (err != ERR_TIMEOUT) { |
||||
/* Errors are only processed in case of an explicit poll response */ |
||||
if (sntp_opmode == SNTP_OPMODE_POLL) { |
||||
if (err == SNTP_ERR_KOD) { |
||||
/* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ |
||||
sntp_try_next_server(NULL); |
||||
} else { |
||||
/* another error, try the same server again */ |
||||
sntp_retry(NULL); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** Actually send an sntp request to a server.
|
||||
* |
||||
* @param server_addr resolved IP address of the SNTP server |
||||
*/ |
||||
static void |
||||
sntp_send_request(const ip_addr_t *server_addr) |
||||
{ |
||||
struct pbuf* p; |
||||
p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); |
||||
if (p != NULL) { |
||||
struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); |
||||
/* initialize request message */ |
||||
sntp_initialize_request(sntpmsg); |
||||
/* send request */ |
||||
udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); |
||||
/* free the pbuf after sending it */ |
||||
pbuf_free(p); |
||||
/* set up receive timeout: try next server or retry on timeout */ |
||||
sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); |
||||
#if SNTP_CHECK_RESPONSE >= 1 |
||||
/* save server address to verify it in sntp_recv */ |
||||
ip_addr_set(&sntp_last_server_address, server_addr); |
||||
#endif /* SNTP_CHECK_RESPONSE >= 1 */ |
||||
} else { |
||||
LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", |
||||
(u32_t)SNTP_RETRY_TIMEOUT)); |
||||
/* out of memory: set up a timer to send a retry */ |
||||
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); |
||||
} |
||||
} |
||||
|
||||
#if SNTP_SERVER_DNS |
||||
/**
|
||||
* DNS found callback when using DNS names as server address. |
||||
*/ |
||||
static void |
||||
sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) |
||||
{ |
||||
LWIP_UNUSED_ARG(hostname); |
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
if (ipaddr != NULL) { |
||||
/* Address resolved, send request */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); |
||||
sntp_send_request(ipaddr); |
||||
} else { |
||||
/* DNS resolving failed -> try another server */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); |
||||
sntp_try_next_server(NULL); |
||||
} |
||||
} |
||||
#endif /* SNTP_SERVER_DNS */ |
||||
|
||||
/**
|
||||
* Send out an sntp request. |
||||
* |
||||
* @param arg is unused (only necessary to conform to sys_timeout) |
||||
*/ |
||||
static void |
||||
sntp_request(void *arg) |
||||
{ |
||||
ip_addr_t sntp_server_address; |
||||
err_t err; |
||||
|
||||
LWIP_UNUSED_ARG(arg); |
||||
|
||||
/* initialize SNTP server address */ |
||||
#if SNTP_SERVER_DNS |
||||
if (sntp_servers[sntp_current_server].name) { |
||||
/* always resolve the name and rely on dns-internal caching & timeout */ |
||||
ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); |
||||
err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, |
||||
sntp_dns_found, NULL); |
||||
if (err == ERR_INPROGRESS) { |
||||
/* DNS request sent, wait for sntp_dns_found being called */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); |
||||
return; |
||||
} else if (err == ERR_OK) { |
||||
sntp_servers[sntp_current_server].addr = sntp_server_address; |
||||
} |
||||
} else |
||||
#endif /* SNTP_SERVER_DNS */ |
||||
{ |
||||
sntp_server_address = sntp_servers[sntp_current_server].addr; |
||||
err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; |
||||
} |
||||
|
||||
if (err == ERR_OK) { |
||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", |
||||
ipaddr_ntoa(&sntp_server_address))); |
||||
sntp_send_request(&sntp_server_address); |
||||
} else { |
||||
/* address conversion failed, try another server */ |
||||
LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); |
||||
sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Initialize this module. |
||||
* Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). |
||||
*/ |
||||
void |
||||
sntp_init(void) |
||||
{ |
||||
#ifdef SNTP_SERVER_ADDRESS |
||||
#if SNTP_SERVER_DNS |
||||
sntp_setservername(0, SNTP_SERVER_ADDRESS); |
||||
#else |
||||
#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 |
||||
#endif |
||||
#endif /* SNTP_SERVER_ADDRESS */ |
||||
|
||||
if (sntp_pcb == NULL) { |
||||
sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); |
||||
LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); |
||||
if (sntp_pcb != NULL) { |
||||
udp_recv(sntp_pcb, sntp_recv, NULL); |
||||
|
||||
if (sntp_opmode == SNTP_OPMODE_POLL) { |
||||
SNTP_RESET_RETRY_TIMEOUT(); |
||||
#if SNTP_STARTUP_DELAY |
||||
sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); |
||||
#else |
||||
sntp_request(NULL); |
||||
#endif |
||||
} else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { |
||||
ip_set_option(sntp_pcb, SOF_BROADCAST); |
||||
udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Stop this module. |
||||
*/ |
||||
void |
||||
sntp_stop(void) |
||||
{ |
||||
if (sntp_pcb != NULL) { |
||||
sys_untimeout(sntp_request, NULL); |
||||
udp_remove(sntp_pcb); |
||||
sntp_pcb = NULL; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Get enabled state. |
||||
*/ |
||||
u8_t sntp_enabled(void) |
||||
{ |
||||
return (sntp_pcb != NULL)? 1 : 0; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Sets the operating mode. |
||||
* @param operating_mode one of the available operating modes |
||||
*/ |
||||
void |
||||
sntp_setoperatingmode(u8_t operating_mode) |
||||
{ |
||||
LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); |
||||
LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); |
||||
sntp_opmode = operating_mode; |
||||
} |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Gets the operating mode. |
||||
*/ |
||||
u8_t |
||||
sntp_getoperatingmode(void) |
||||
{ |
||||
return sntp_opmode; |
||||
} |
||||
|
||||
#if SNTP_GET_SERVERS_FROM_DHCP |
||||
/**
|
||||
* Config SNTP server handling by IP address, name, or DHCP; clear table |
||||
* @param set_servers_from_dhcp enable or disable getting server addresses from dhcp |
||||
*/ |
||||
void |
||||
sntp_servermode_dhcp(int set_servers_from_dhcp) |
||||
{ |
||||
u8_t new_mode = set_servers_from_dhcp ? 1 : 0; |
||||
if (sntp_set_servers_from_dhcp != new_mode) { |
||||
sntp_set_servers_from_dhcp = new_mode; |
||||
} |
||||
} |
||||
#endif /* SNTP_GET_SERVERS_FROM_DHCP */ |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Initialize one of the NTP servers by IP address |
||||
* |
||||
* @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS |
||||
* @param server IP address of the NTP server to set |
||||
*/ |
||||
void |
||||
sntp_setserver(u8_t idx, const ip_addr_t *server) |
||||
{ |
||||
if (idx < SNTP_MAX_SERVERS) { |
||||
if (server != NULL) { |
||||
sntp_servers[idx].addr = (*server); |
||||
} else { |
||||
ip_addr_set_zero(&sntp_servers[idx].addr); |
||||
} |
||||
#if SNTP_SERVER_DNS |
||||
sntp_servers[idx].name = NULL; |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP |
||||
/**
|
||||
* Initialize one of the NTP servers by IP address, required by DHCP |
||||
* |
||||
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS |
||||
* @param dnsserver IP address of the NTP server to set |
||||
*/ |
||||
void |
||||
dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) |
||||
{ |
||||
LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", |
||||
(sntp_set_servers_from_dhcp ? "Got" : "Rejected"), |
||||
ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); |
||||
if (sntp_set_servers_from_dhcp && num) { |
||||
u8_t i; |
||||
for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { |
||||
ip_addr_t addr; |
||||
ip_addr_copy_from_ip4(addr, server[i]); |
||||
sntp_setserver(i, &addr); |
||||
} |
||||
for (i = num; i < SNTP_MAX_SERVERS; i++) { |
||||
sntp_setserver(i, NULL); |
||||
} |
||||
} |
||||
} |
||||
#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ |
||||
|
||||
/**
|
||||
* @ingroup sntp |
||||
* Obtain one of the currently configured by IP address (or DHCP) NTP servers |
||||
* |
||||
* @param idx the index of the NTP server |
||||
* @return IP address of the indexed NTP server or "ip_addr_any" if the NTP |
||||
* server has not been configured by address (or at all). |
||||
*/ |
||||
const ip_addr_t* |
||||
sntp_getserver(u8_t idx) |
||||
{ |
||||
if (idx < SNTP_MAX_SERVERS) { |
||||
return &sntp_servers[idx].addr; |
||||
} |
||||
return IP_ADDR_ANY; |
||||
} |
||||
|
||||
#if SNTP_SERVER_DNS |
||||
/**
|
||||
* Initialize one of the NTP servers by name |
||||
* |
||||
* @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS |
||||
* @param dnsserver DNS name of the NTP server to set, to be resolved at contact time |
||||
*/ |
||||
void |
||||
sntp_setservername(u8_t idx, char *server) |
||||
{ |
||||
if (idx < SNTP_MAX_SERVERS) { |
||||
sntp_servers[idx].name = server; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* Obtain one of the currently configured by name NTP servers. |
||||
* |
||||
* @param numdns the index of the NTP server |
||||
* @return IP address of the indexed NTP server or NULL if the NTP |
||||
* server has not been configured by name (or at all) |
||||
*/ |
||||
char * |
||||
sntp_getservername(u8_t idx) |
||||
{ |
||||
if (idx < SNTP_MAX_SERVERS) { |
||||
return sntp_servers[idx].name; |
||||
} |
||||
return NULL; |
||||
} |
||||
#endif /* SNTP_SERVER_DNS */ |
||||
|
||||
#endif /* LWIP_UDP */ |
||||
Loading…
Reference in new issue