mirror of
				https://github.com/pvvx/RTL00MP3.git
				synced 2025-07-31 12:41:06 +00:00 
			
		
		
		
	update
This commit is contained in:
		
							parent
							
								
									629e5fdc28
								
							
						
					
					
						commit
						bd42ffa334
					
				
					 212 changed files with 35447 additions and 223 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								RTL00_SDKV35a/component/common/api/at_cmd/atcmd_sys.zip
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								RTL00_SDKV35a/component/common/api/at_cmd/atcmd_sys.zip
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -90,7 +90,7 @@ | |||
| 		#define printf                  DiagPrintfPatch | ||||
| 		#define sprintf					DiagSPrintfPatch | ||||
| 		#define snprintf				DiagSnPrintfPatch | ||||
| 		#define strstr(a, b)					DiagStrstrPatch((char *)(a), (char *)(b)) | ||||
| 		#define strstr(a, b)			DiagStrstrPatch((char *)(a), (char *)(b)) | ||||
| 		#define strtok					DiagStrtokPatch | ||||
| 	#else | ||||
| 		#define printf                  DiagPrintf | ||||
|  |  | |||
|  | @ -44,6 +44,10 @@ typedef signed short int	s16; | |||
| typedef unsigned char		bool; | ||||
| 
 | ||||
| 
 | ||||
| extern u8 txt0123456789ABCDEF[16]; | ||||
| #define tab0123456789ABCDEF txt0123456789ABCDEF // = "0123456789ABCDEF"
 | ||||
| 
 | ||||
| 
 | ||||
| #define in_range(c, lo, up)  ((u8)c >= lo && (u8)c <= up) | ||||
| #define isprint(c)           in_range(c, 0x20, 0x7f) | ||||
| #define isdigit(c)           in_range(c, '0', '9') | ||||
|  | @ -644,7 +648,7 @@ int DiagSnPrintfPatch(char *buf, size_t size, const char *fmt, ...) | |||
| 					shift = (hex_count - 1)*4; | ||||
| 
 | ||||
| 				for(; shift >= 0; shift -= 4) | ||||
| 					*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; | ||||
| 					*q++ = tab0123456789ABCDEF[(h >> shift) & 0xF] | ncase; | ||||
| 			} | ||||
| 			else if(*fmt == 'd') { | ||||
| 				int i = *dp++; | ||||
|  | @ -825,7 +829,7 @@ static int VSprintfPatch(char *buf, const char *fmt, const int *dp) | |||
| 
 | ||||
| 				for(; shift >= 0; shift -= 4) { | ||||
| 
 | ||||
| 					*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; | ||||
| 					*q++ = tab0123456789ABCDEF[(h >> shift) & 0xF] | ncase; | ||||
| 				} | ||||
| 
 | ||||
| 			} | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ const unsigned char *eap_client_cert = NULL; | |||
| const unsigned char *eap_client_key = NULL; | ||||
| char *eap_client_key_pwd = NULL; | ||||
| 
 | ||||
| //int max_buf_bio_size = SSL_BUFFER_LEN;
 | ||||
| //int max_buf_bio_size = SSL_BUFFER_LEN; // ?pvvx?
 | ||||
| 
 | ||||
| #ifdef CONFIG_ENABLE_EAP | ||||
| void eap_eapol_recvd_hdl(char *buf, int buf_len, int flags, void* handler_user_data); | ||||
|  |  | |||
|  | @ -978,7 +978,7 @@ u8 OTU_check_gpio(void) | |||
|     GPIO_Pin.pin_name = HAL_GPIO_GetIPPinName_8195a(0x21); //pin PC_1
 | ||||
|     GPIO_Pin.pin_mode = DIN_PULL_HIGH; | ||||
| 
 | ||||
|     _pHAL_Gpio_Adapter = &gBoot_Gpio_Adapter; | ||||
| //    _pHAL_Gpio_Adapter = &gBoot_Gpio_Adapter;
 | ||||
|     | ||||
|     HAL_GPIO_Init_8195a(&GPIO_Pin); | ||||
|     if (HAL_GPIO_ReadPin_8195a(&GPIO_Pin) == GPIO_PIN_LOW) { | ||||
|  | @ -989,7 +989,7 @@ u8 OTU_check_gpio(void) | |||
|     } | ||||
|     HAL_GPIO_DeInit_8195a(&GPIO_Pin); | ||||
| 
 | ||||
|     _pHAL_Gpio_Adapter = NULL; | ||||
| //    _pHAL_Gpio_Adapter = NULL;
 | ||||
|     return enter_update; | ||||
| #else | ||||
|     return 0; | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -0,0 +1,174 @@ | |||
| /*
 | ||||
|  * 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 <string.h> | ||||
| 
 | ||||
| 
 | ||||
| #include HTTPD_FSDATA_FILE | ||||
| 
 | ||||
| /*-----------------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #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; | ||||
| } | ||||
|  | @ -0,0 +1,21 @@ | |||
| <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> | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 724 B | 
|  | @ -0,0 +1,47 @@ | |||
| <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> | ||||
| 
 | ||||
|  | @ -0,0 +1,297 @@ | |||
| #include "lwip/apps/fs.h" | ||||
| #include "lwip/def.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 | ||||
| 
 | ||||
|  | @ -0,0 +1,41 @@ | |||
| /*
 | ||||
|  * 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" | ||||
| 
 | ||||
| /* THIS FILE IS DEPRECATED AND WILL BE REMOVED IN THE FUTURE */ | ||||
| /* content was moved to fs.h to simplify #include structure */ | ||||
| 
 | ||||
| #endif /* LWIP_FSDATA_H */ | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -0,0 +1,114 @@ | |||
| #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 */ | ||||
|  | @ -0,0 +1,97 @@ | |||
| #!/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
											
										
									
								
							|  | @ -0,0 +1,13 @@ | |||
| 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'. | ||||
|  | @ -0,0 +1,661 @@ | |||
| /**
 | ||||
|  * @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)lwip_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 = lwip_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 = LWIP_CONST_CAST(void*, &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)lwip_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) | ||||
| { | ||||
|   u8_t tmp; | ||||
|   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... */ | ||||
|     tmp = pbuf_header(p, -24); | ||||
|     LWIP_ASSERT("pbuf_header failed", tmp == 0); | ||||
|   } | ||||
| 
 | ||||
|   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; | ||||
|       } | ||||
|     } | ||||
| #endif | ||||
|     packet_idx += q->len; | ||||
|   } | ||||
|   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 */ | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -0,0 +1,367 @@ | |||
| /**
 | ||||
|  * @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/def.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 (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(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! */ | ||||
|     ip_set_option(netbiosns_pcb, 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 */ | ||||
|  | @ -0,0 +1,749 @@ | |||
| /**
 | ||||
|  * @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 parameter 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 value to be encoded | ||||
|  * @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 value to be encoded | ||||
|  * @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 value to be encoded | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,108 @@ | |||
| /**
 | ||||
|  * @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
											
										
									
								
							|  | @ -0,0 +1,76 @@ | |||
| /*
 | ||||
|  * 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 */ | ||||
|  | @ -0,0 +1,116 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,182 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,375 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,743 @@ | |||
| /**
 | ||||
|  * @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 instance node instance | ||||
|  * @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_ANY4->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_ANY4->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_ANY4, &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), LWIP_PTR_NUMERIC_CAST(void*, 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(LWIP_PTR_NUMERIC_CAST(u8_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 */ | ||||
|  | @ -0,0 +1,227 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,377 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,594 @@ | |||
| /**
 | ||||
|  * @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_ANY4->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_ANY4) && (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_ANY4, &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 */ | ||||
|  | @ -0,0 +1,357 @@ | |||
| /**
 | ||||
|  * @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
											
										
									
								
							|  | @ -0,0 +1,194 @@ | |||
| /**
 | ||||
|  * @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 enum { | ||||
|   SNMP_VB_ENUMERATOR_ERR_OK            = 0, | ||||
|   SNMP_VB_ENUMERATOR_ERR_EOVB          = 1, | ||||
|   SNMP_VB_ENUMERATOR_ERR_ASN1ERROR     = 2, | ||||
|   SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 | ||||
| } snmp_vb_enumerator_err_t; | ||||
| 
 | ||||
| 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 */ | ||||
|  | @ -0,0 +1,121 @@ | |||
| /**
 | ||||
|  * @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 <string.h> | ||||
| #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, IP4_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 */ | ||||
|  | @ -0,0 +1,156 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,73 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,100 @@ | |||
| /**
 | ||||
|  * @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_ANY_TYPE 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 */ | ||||
|  | @ -0,0 +1,220 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,343 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,219 @@ | |||
| /**
 | ||||
|  * @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_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ | ||||
|   LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); | ||||
|   instance->sync_fn = sync_fn; | ||||
| } | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
|  | @ -0,0 +1,445 @@ | |||
| /**
 | ||||
|  * @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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup snmp_traps | ||||
|  * Sends a generic or enterprise specific trap message. | ||||
|  * | ||||
|  * @param eoid points to enterprise object identifier | ||||
|  * @param generic_trap is the trap code | ||||
|  * @param specific_trap used for enterprise traps when generic_trap == 6 | ||||
|  * @param varbinds linked list of varbinds to be sent | ||||
|  * @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. | ||||
|  */ | ||||
| err_t | ||||
| snmp_send_trap(const struct snmp_obj_id* eoid, 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 (eoid == NULL) { | ||||
|           trap_msg.enterprise = snmp_get_device_enterprise_oid(); | ||||
|         } else { | ||||
|           trap_msg.enterprise = eoid; | ||||
|         } | ||||
| 
 | ||||
|         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 trap Trap message | ||||
|  * @param vb_len varbind-list length | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,136 @@ | |||
| /**
 | ||||
|  * @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(); | ||||
|   } | ||||
| 
 | ||||
|   SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); | ||||
|   SMEMCPY(&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(); | ||||
|   SMEMCPY(&priv_param[0], &boots, 4); | ||||
|   SMEMCPY(&priv_param[4], &ctr, 4); | ||||
|   ctr++; | ||||
| #endif | ||||
|   return ERR_OK; | ||||
| } | ||||
| #endif /* LWIP_SNMP_V3_CRYPTO */ | ||||
| 
 | ||||
| #endif | ||||
|  | @ -0,0 +1,145 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,331 @@ | |||
| /**
 | ||||
|  * @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; | ||||
|     SMEMCPY(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     */ | ||||
|   /*****************************************************/ | ||||
|   SMEMCPY(password_buf, key, 16); | ||||
|   MEMCPY(password_buf + 16, engineID, engineLength); | ||||
|   SMEMCPY(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     */ | ||||
|   /*****************************************************/ | ||||
|   SMEMCPY(password_buf, key, 20); | ||||
|   MEMCPY(password_buf + 20, engineID, engineLength); | ||||
|   SMEMCPY(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 */ | ||||
|  | @ -0,0 +1,66 @@ | |||
| /**
 | ||||
|  * @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 */ | ||||
|  | @ -0,0 +1,727 @@ | |||
| /**
 | ||||
|  * @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 = lwip_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 = lwip_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] = lwip_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] = lwip_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); | ||||
|     sys_untimeout(sntp_try_next_server, 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 */ | ||||
|  | @ -0,0 +1,417 @@ | |||
| /****************************************************************//**
 | ||||
|  * | ||||
|  * @file tftp_server.c | ||||
|  * | ||||
|  * @author   Logan Gunthorpe <logang@deltatee.com> | ||||
|  *           Dirk Ziegelmeier <dziegel@gmx.de> | ||||
|  * | ||||
|  * @brief    Trivial File Transfer Protocol (RFC 1350) | ||||
|  * | ||||
|  * Copyright (c) Deltatee Enterprises Ltd. 2013 | ||||
|  * 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: Logan Gunthorpe <logang@deltatee.com> | ||||
|  *         Dirk Ziegelmeier <dziegel@gmx.de> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup tftp TFTP server | ||||
|  * @ingroup apps | ||||
|  * | ||||
|  * This is simple TFTP server for the lwIP raw API. | ||||
|  */ | ||||
| 
 | ||||
| #include "lwip/apps/tftp_server.h" | ||||
| 
 | ||||
| #if LWIP_UDP | ||||
| 
 | ||||
| #include "lwip/udp.h" | ||||
| #include "lwip/timeouts.h" | ||||
| #include "lwip/debug.h" | ||||
| 
 | ||||
| #define TFTP_MAX_PAYLOAD_SIZE 512 | ||||
| #define TFTP_HEADER_LENGTH    4 | ||||
| 
 | ||||
| #define TFTP_RRQ   1 | ||||
| #define TFTP_WRQ   2 | ||||
| #define TFTP_DATA  3 | ||||
| #define TFTP_ACK   4 | ||||
| #define TFTP_ERROR 5 | ||||
| 
 | ||||
| enum tftp_error { | ||||
|   TFTP_ERROR_FILE_NOT_FOUND    = 1, | ||||
|   TFTP_ERROR_ACCESS_VIOLATION  = 2, | ||||
|   TFTP_ERROR_DISK_FULL         = 3, | ||||
|   TFTP_ERROR_ILLEGAL_OPERATION = 4, | ||||
|   TFTP_ERROR_UNKNOWN_TRFR_ID   = 5, | ||||
|   TFTP_ERROR_FILE_EXISTS       = 6, | ||||
|   TFTP_ERROR_NO_SUCH_USER      = 7 | ||||
| }; | ||||
| 
 | ||||
| #include <string.h> | ||||
| 
 | ||||
| struct tftp_state { | ||||
|   const struct tftp_context *ctx; | ||||
|   void *handle; | ||||
|   struct pbuf *last_data; | ||||
|   struct udp_pcb *upcb; | ||||
|   ip_addr_t addr; | ||||
|   u16_t port; | ||||
|   int timer; | ||||
|   int last_pkt; | ||||
|   u16_t blknum; | ||||
|   u8_t retries; | ||||
|   u8_t mode_write; | ||||
| }; | ||||
| 
 | ||||
| static struct tftp_state tftp_state; | ||||
| 
 | ||||
| static void tftp_tmr(void* arg); | ||||
| 
 | ||||
| static void | ||||
| close_handle(void) | ||||
| { | ||||
|   tftp_state.port = 0; | ||||
|   ip_addr_set_any(0, &tftp_state.addr); | ||||
| 
 | ||||
|   if(tftp_state.last_data != NULL) { | ||||
|     pbuf_free(tftp_state.last_data); | ||||
|     tftp_state.last_data = NULL; | ||||
|   } | ||||
| 
 | ||||
|   sys_untimeout(tftp_tmr, NULL); | ||||
|    | ||||
|   if (tftp_state.handle) { | ||||
|     tftp_state.ctx->close(tftp_state.handle); | ||||
|     tftp_state.handle = NULL; | ||||
|     LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) | ||||
| { | ||||
|   int str_length = strlen(str); | ||||
|   struct pbuf* p; | ||||
|   u16_t* payload; | ||||
|    | ||||
|   p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); | ||||
|   if(p == NULL) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   payload = (u16_t*) p->payload; | ||||
|   payload[0] = PP_HTONS(TFTP_ERROR); | ||||
|   payload[1] = lwip_htons(code); | ||||
|   MEMCPY(&payload[2], str, str_length + 1); | ||||
| 
 | ||||
|   udp_sendto(tftp_state.upcb, p, addr, port); | ||||
|   pbuf_free(p); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| send_ack(u16_t blknum) | ||||
| { | ||||
|   struct pbuf* p; | ||||
|   u16_t* payload; | ||||
|    | ||||
|   p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); | ||||
|   if(p == NULL) { | ||||
|     return; | ||||
|   } | ||||
|   payload = (u16_t*) p->payload; | ||||
|    | ||||
|   payload[0] = PP_HTONS(TFTP_ACK); | ||||
|   payload[1] = lwip_htons(blknum); | ||||
|   udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); | ||||
|   pbuf_free(p); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| resend_data(void) | ||||
| { | ||||
|   struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); | ||||
|   if(p == NULL) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   if(pbuf_copy(p, tftp_state.last_data) != ERR_OK) { | ||||
|     pbuf_free(p); | ||||
|     return; | ||||
|   } | ||||
|      | ||||
|   udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); | ||||
|   pbuf_free(p); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| send_data(void) | ||||
| { | ||||
|   u16_t *payload; | ||||
|   int ret; | ||||
| 
 | ||||
|   if(tftp_state.last_data != NULL) { | ||||
|     pbuf_free(tftp_state.last_data); | ||||
|   } | ||||
|    | ||||
|   tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); | ||||
|   if(tftp_state.last_data == NULL) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   payload = (u16_t *) tftp_state.last_data->payload; | ||||
|   payload[0] = PP_HTONS(TFTP_DATA); | ||||
|   payload[1] = lwip_htons(tftp_state.blknum); | ||||
| 
 | ||||
|   ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); | ||||
|   if (ret < 0) { | ||||
|     send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); | ||||
|     close_handle(); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); | ||||
|   resend_data(); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) | ||||
| { | ||||
|   u16_t *sbuf = (u16_t *) p->payload; | ||||
|   int opcode; | ||||
| 
 | ||||
|   LWIP_UNUSED_ARG(arg); | ||||
|   LWIP_UNUSED_ARG(upcb); | ||||
|    | ||||
|   if (((tftp_state.port != 0) && (port != tftp_state.port)) || | ||||
|       (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { | ||||
|     send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); | ||||
|     pbuf_free(p); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   opcode = sbuf[0]; | ||||
| 
 | ||||
|   tftp_state.last_pkt = tftp_state.timer; | ||||
|   tftp_state.retries = 0; | ||||
| 
 | ||||
|   switch (opcode) { | ||||
|     case PP_HTONS(TFTP_RRQ): /* fall through */ | ||||
|     case PP_HTONS(TFTP_WRQ): | ||||
|     { | ||||
|       const char tftp_null = 0; | ||||
|       char filename[TFTP_MAX_FILENAME_LEN]; | ||||
|       char mode[TFTP_MAX_MODE_LEN]; | ||||
|       u16_t filename_end_offset; | ||||
|       u16_t mode_end_offset; | ||||
| 
 | ||||
|       if(tftp_state.handle != NULL) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); | ||||
|         break; | ||||
|       } | ||||
|        | ||||
|       sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); | ||||
| 
 | ||||
|       /* find \0 in pbuf -> end of filename string */ | ||||
|       filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); | ||||
|       if((u16_t)(filename_end_offset-2) > sizeof(filename)) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); | ||||
|         break; | ||||
|       } | ||||
|       pbuf_copy_partial(p, filename, filename_end_offset-2, 2); | ||||
| 
 | ||||
|       /* find \0 in pbuf -> end of mode string */ | ||||
|       mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset+1); | ||||
|       if((u16_t)(mode_end_offset-filename_end_offset) > sizeof(mode)) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); | ||||
|         break; | ||||
|       } | ||||
|       pbuf_copy_partial(p, mode, mode_end_offset-filename_end_offset, filename_end_offset+1); | ||||
|   | ||||
|       tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); | ||||
|       tftp_state.blknum = 1; | ||||
| 
 | ||||
|       if (!tftp_state.handle) { | ||||
|         send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); | ||||
|       ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); | ||||
|       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); | ||||
| 
 | ||||
|       ip_addr_copy(tftp_state.addr, *addr); | ||||
|       tftp_state.port = port; | ||||
| 
 | ||||
|       if (opcode == PP_HTONS(TFTP_WRQ)) { | ||||
|         tftp_state.mode_write = 1; | ||||
|         send_ack(0); | ||||
|       } else { | ||||
|         tftp_state.mode_write = 0; | ||||
|         send_data(); | ||||
|       } | ||||
| 
 | ||||
|       break; | ||||
|     } | ||||
|      | ||||
|     case PP_HTONS(TFTP_DATA): | ||||
|     { | ||||
|       int ret; | ||||
|       u16_t blknum; | ||||
|        | ||||
|       if (tftp_state.handle == NULL) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       if (tftp_state.mode_write != 1) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       blknum = lwip_ntohs(sbuf[1]); | ||||
|       pbuf_header(p, -TFTP_HEADER_LENGTH); | ||||
| 
 | ||||
|       ret = tftp_state.ctx->write(tftp_state.handle, p); | ||||
|       if (ret < 0) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); | ||||
|         close_handle(); | ||||
|       } else { | ||||
|         send_ack(blknum); | ||||
|       } | ||||
| 
 | ||||
|       if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { | ||||
|         close_handle(); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     case PP_HTONS(TFTP_ACK): | ||||
|     { | ||||
|       u16_t blknum; | ||||
|       int lastpkt; | ||||
| 
 | ||||
|       if (tftp_state.handle == NULL) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       if (tftp_state.mode_write != 0) { | ||||
|         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       blknum = lwip_ntohs(sbuf[1]); | ||||
|       if (blknum != tftp_state.blknum) { | ||||
|         send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); | ||||
|         break; | ||||
|       } | ||||
| 
 | ||||
|       lastpkt = 0; | ||||
| 
 | ||||
|       if (tftp_state.last_data != NULL) { | ||||
|         lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); | ||||
|       } | ||||
| 
 | ||||
|       if (!lastpkt) { | ||||
|         tftp_state.blknum++; | ||||
|         send_data(); | ||||
|       } else { | ||||
|         close_handle(); | ||||
|       } | ||||
| 
 | ||||
|       break; | ||||
|     } | ||||
|      | ||||
|     default: | ||||
|       send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   pbuf_free(p); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| tftp_tmr(void* arg) | ||||
| { | ||||
|   LWIP_UNUSED_ARG(arg); | ||||
|    | ||||
|   tftp_state.timer++; | ||||
| 
 | ||||
|   if (tftp_state.handle == NULL) { | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); | ||||
| 
 | ||||
|   if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { | ||||
|     if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { | ||||
|       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); | ||||
|       resend_data(); | ||||
|       tftp_state.retries++; | ||||
|     } else { | ||||
|       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); | ||||
|       close_handle(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** @ingroup tftp
 | ||||
|  * Initialize TFTP server. | ||||
|  * @param ctx TFTP callback struct | ||||
|  */ | ||||
| err_t  | ||||
| tftp_init(const struct tftp_context *ctx) | ||||
| { | ||||
|   err_t ret; | ||||
| 
 | ||||
|   struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); | ||||
|   if (pcb == NULL) { | ||||
|     return ERR_MEM; | ||||
|   } | ||||
| 
 | ||||
|   ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); | ||||
|   if (ret != ERR_OK) { | ||||
|     udp_remove(pcb); | ||||
|     return ret; | ||||
|   } | ||||
| 
 | ||||
|   tftp_state.handle    = NULL; | ||||
|   tftp_state.port      = 0; | ||||
|   tftp_state.ctx       = ctx; | ||||
|   tftp_state.timer     = 0; | ||||
|   tftp_state.last_data = NULL; | ||||
|   tftp_state.upcb      = pcb; | ||||
| 
 | ||||
|   udp_recv(pcb, recv, NULL); | ||||
| 
 | ||||
|   return ERR_OK; | ||||
| } | ||||
| 
 | ||||
| #endif /* LWIP_UDP */ | ||||
|  | @ -103,45 +103,6 @@ | |||
| #define DNS_MAX_TTL               604800 | ||||
| #endif | ||||
| 
 | ||||
| /* DNS protocol flags */ | ||||
| #define DNS_FLAG1_RESPONSE        0x80 | ||||
| #define DNS_FLAG1_OPCODE_STATUS   0x10 | ||||
| #define DNS_FLAG1_OPCODE_INVERSE  0x08 | ||||
| #define DNS_FLAG1_OPCODE_STANDARD 0x00 | ||||
| #define DNS_FLAG1_AUTHORATIVE     0x04 | ||||
| #define DNS_FLAG1_TRUNC           0x02 | ||||
| #define DNS_FLAG1_RD              0x01 | ||||
| #define DNS_FLAG2_RA              0x80 | ||||
| #define DNS_FLAG2_ERR_MASK        0x0f | ||||
| #define DNS_FLAG2_ERR_NONE        0x00 | ||||
| #define DNS_FLAG2_ERR_NAME        0x03 | ||||
| 
 | ||||
| /* DNS protocol states */ | ||||
| #define DNS_STATE_UNUSED          0 | ||||
| #define DNS_STATE_NEW             1 | ||||
| #define DNS_STATE_ASKING          2 | ||||
| #define DNS_STATE_DONE            3 | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** DNS message header */ | ||||
| struct dns_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t id); | ||||
|   PACK_STRUCT_FIELD(u8_t flags1); | ||||
|   PACK_STRUCT_FIELD(u8_t flags2); | ||||
|   PACK_STRUCT_FIELD(u16_t numquestions); | ||||
|   PACK_STRUCT_FIELD(u16_t numanswers); | ||||
|   PACK_STRUCT_FIELD(u16_t numauthrr); | ||||
|   PACK_STRUCT_FIELD(u16_t numextrarr); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| #define SIZEOF_DNS_HDR 12 | ||||
| 
 | ||||
| /** DNS query message structure.
 | ||||
|     No packing needed: only used locally on the stack. */ | ||||
| struct dns_query { | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| This directory contains application headers. | ||||
| Every application shall provide one api file APP.h and optionally one options file APP_opts.h | ||||
|  | @ -0,0 +1,115 @@ | |||
| /*
 | ||||
|  * 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_HDR_APPS_FS_H | ||||
| #define LWIP_HDR_APPS_FS_H | ||||
| 
 | ||||
| #include "httpd_opts.h" | ||||
| #include "lwip/err.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define FS_READ_EOF     -1 | ||||
| #define FS_READ_DELAYED -2 | ||||
| 
 | ||||
| #if HTTPD_PRECALCULATED_CHECKSUM | ||||
| struct fsdata_chksum { | ||||
|   u32_t offset; | ||||
|   u16_t chksum; | ||||
|   u16_t len; | ||||
| }; | ||||
| #endif /* HTTPD_PRECALCULATED_CHECKSUM */ | ||||
| 
 | ||||
| #define FS_FILE_FLAGS_HEADER_INCLUDED     0x01 | ||||
| #define FS_FILE_FLAGS_HEADER_PERSISTENT   0x02 | ||||
| 
 | ||||
| struct fs_file { | ||||
|   const char *data; | ||||
|   int len; | ||||
|   int index; | ||||
|   void *pextension; | ||||
| #if HTTPD_PRECALCULATED_CHECKSUM | ||||
|   const struct fsdata_chksum *chksum; | ||||
|   u16_t chksum_count; | ||||
| #endif /* HTTPD_PRECALCULATED_CHECKSUM */ | ||||
|   u8_t flags; | ||||
| #if LWIP_HTTPD_CUSTOM_FILES | ||||
|   u8_t is_custom_file; | ||||
| #endif /* LWIP_HTTPD_CUSTOM_FILES */ | ||||
| #if LWIP_HTTPD_FILE_STATE | ||||
|   void *state; | ||||
| #endif /* LWIP_HTTPD_FILE_STATE */ | ||||
| }; | ||||
| 
 | ||||
| #if LWIP_HTTPD_FS_ASYNC_READ | ||||
| typedef void (*fs_wait_cb)(void *arg); | ||||
| #endif /* LWIP_HTTPD_FS_ASYNC_READ */ | ||||
| 
 | ||||
| err_t fs_open(struct fs_file *file, const char *name); | ||||
| void fs_close(struct fs_file *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 */ | ||||
| #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); | ||||
| #endif /* LWIP_HTTPD_FS_ASYNC_READ */ | ||||
| int fs_bytes_left(struct fs_file *file); | ||||
| 
 | ||||
| #if LWIP_HTTPD_FILE_STATE | ||||
| /** This user-defined function is called when a file is opened. */ | ||||
| void *fs_state_init(struct fs_file *file, const char *name); | ||||
| /** This user-defined function is called when a file is closed. */ | ||||
| void fs_state_free(struct fs_file *file, void *state); | ||||
| #endif /* #if LWIP_HTTPD_FILE_STATE */ | ||||
| 
 | ||||
| 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 */ | ||||
| }; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_FS_H */ | ||||
|  | @ -0,0 +1,236 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * HTTP server | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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> | ||||
|  * | ||||
|  * This version of the file has been modified by Texas Instruments to offer | ||||
|  * simple server-side-include (SSI) and Common Gateway Interface (CGI) | ||||
|  * capability. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_HTTPD_H | ||||
| #define LWIP_HDR_APPS_HTTPD_H | ||||
| 
 | ||||
| #include "httpd_opts.h" | ||||
| #include "lwip/err.h" | ||||
| #include "lwip/pbuf.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_HTTPD_CGI | ||||
| 
 | ||||
| /*
 | ||||
|  * Function pointer for a CGI script handler. | ||||
|  * | ||||
|  * This function is called each time the HTTPD server is asked for a file | ||||
|  * whose name was previously registered as a CGI function using a call to | ||||
|  * http_set_cgi_handler. The iIndex parameter provides the index of the | ||||
|  * CGI within the ppcURLs array passed to http_set_cgi_handler. Parameters | ||||
|  * pcParam and pcValue provide access to the parameters provided along with | ||||
|  * the URI. iNumParams provides a count of the entries in the pcParam and | ||||
|  * pcValue arrays. Each entry in the pcParam array contains the name of a | ||||
|  * parameter with the corresponding entry in the pcValue array containing the | ||||
|  * value for that parameter. Note that pcParam may contain multiple elements | ||||
|  * with the same name if, for example, a multi-selection list control is used | ||||
|  * in the form generating the data. | ||||
|  * | ||||
|  * The function should return a pointer to a character string which is the | ||||
|  * path and filename of the response that is to be sent to the connected | ||||
|  * browser, for example "/thanks.htm" or "/response/error.ssi". | ||||
|  * | ||||
|  * The maximum number of parameters that will be passed to this function via | ||||
|  * iNumParams is defined by LWIP_HTTPD_MAX_CGI_PARAMETERS. Any parameters in the incoming | ||||
|  * HTTP request above this number will be discarded. | ||||
|  * | ||||
|  * Requests intended for use by this CGI mechanism must be sent using the GET | ||||
|  * method (which encodes all parameters within the URI rather than in a block | ||||
|  * later in the request). Attempts to use the POST method will result in the | ||||
|  * request being ignored. | ||||
|  * | ||||
|  */ | ||||
| typedef const char *(*tCGIHandler)(int iIndex, int iNumParams, char *pcParam[], | ||||
|                              char *pcValue[]); | ||||
| 
 | ||||
| /*
 | ||||
|  * Structure defining the base filename (URL) of a CGI and the associated | ||||
|  * function which is to be called when that URL is requested. | ||||
|  */ | ||||
| typedef struct | ||||
| { | ||||
|     const char *pcCGIName; | ||||
|     tCGIHandler pfnCGIHandler; | ||||
| } tCGI; | ||||
| 
 | ||||
| void http_set_cgi_handlers(const tCGI *pCGIs, int iNumHandlers); | ||||
| 
 | ||||
| #endif /* LWIP_HTTPD_CGI */ | ||||
| 
 | ||||
| #if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI | ||||
| 
 | ||||
| #if LWIP_HTTPD_CGI_SSI | ||||
| /** Define this generic CGI handler in your application.
 | ||||
|  * It is called once for every URI with parameters. | ||||
|  * The parameters can be stored to  | ||||
|  */ | ||||
| extern void httpd_cgi_handler(const char* uri, int iNumParams, char **pcParam, char **pcValue | ||||
| #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE | ||||
|                                      , void *connection_state | ||||
| #endif /* LWIP_HTTPD_FILE_STATE */ | ||||
|                                      ); | ||||
| #endif /* LWIP_HTTPD_CGI_SSI */ | ||||
| 
 | ||||
| #endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ | ||||
| 
 | ||||
| #if LWIP_HTTPD_SSI | ||||
| 
 | ||||
| /*
 | ||||
|  * Function pointer for the SSI tag handler callback. | ||||
|  * | ||||
|  * This function will be called each time the HTTPD server detects a tag of the | ||||
|  * form <!--#name--> in a .shtml, .ssi or .shtm file where "name" appears as | ||||
|  * one of the tags supplied to http_set_ssi_handler in the ppcTags array.  The | ||||
|  * returned insert string, which will be appended after the the string | ||||
|  * "<!--#name-->" in file sent back to the client,should be written to pointer | ||||
|  * pcInsert.  iInsertLen contains the size of the buffer pointed to by | ||||
|  * pcInsert.  The iIndex parameter provides the zero-based index of the tag as | ||||
|  * found in the ppcTags array and identifies the tag that is to be processed. | ||||
|  * | ||||
|  * The handler returns the number of characters written to pcInsert excluding | ||||
|  * any terminating NULL or a negative number to indicate a failure (tag not | ||||
|  * recognized, for example). | ||||
|  * | ||||
|  * Note that the behavior of this SSI mechanism is somewhat different from the | ||||
|  * "normal" SSI processing as found in, for example, the Apache web server.  In | ||||
|  * this case, the inserted text is appended following the SSI tag rather than | ||||
|  * replacing the tag entirely.  This allows for an implementation that does not | ||||
|  * require significant additional buffering of output data yet which will still | ||||
|  * offer usable SSI functionality.  One downside to this approach is when | ||||
|  * attempting to use SSI within JavaScript.  The SSI tag is structured to | ||||
|  * resemble an HTML comment but this syntax does not constitute a comment | ||||
|  * within JavaScript and, hence, leaving the tag in place will result in | ||||
|  * problems in these cases.  To work around this, any SSI tag which needs to | ||||
|  * output JavaScript code must do so in an encapsulated way, sending the whole | ||||
|  * HTML <script>...</script> section as a single include. | ||||
|  */ | ||||
| typedef u16_t (*tSSIHandler)( | ||||
| #if LWIP_HTTPD_SSI_RAW | ||||
|                              const char* ssi_tag_name, | ||||
| #else /* LWIP_HTTPD_SSI_RAW */ | ||||
|                              int iIndex, | ||||
| #endif /* LWIP_HTTPD_SSI_RAW */ | ||||
|                              char *pcInsert, int iInsertLen | ||||
| #if LWIP_HTTPD_SSI_MULTIPART | ||||
|                              , u16_t current_tag_part, u16_t *next_tag_part | ||||
| #endif /* LWIP_HTTPD_SSI_MULTIPART */ | ||||
| #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE | ||||
|                              , void *connection_state | ||||
| #endif /* LWIP_HTTPD_FILE_STATE */ | ||||
|                              ); | ||||
| 
 | ||||
| /** Set the SSI handler function
 | ||||
|  * (if LWIP_HTTPD_SSI_RAW==1, only the first argument is used) | ||||
|  */ | ||||
| void http_set_ssi_handler(tSSIHandler pfnSSIHandler, | ||||
|                           const char **ppcTags, int iNumTags); | ||||
| 
 | ||||
| /** For LWIP_HTTPD_SSI_RAW==1, return this to indicate the tag is unknown.
 | ||||
|  * In this case, the webserver writes a warning into the page. | ||||
|  * You can also just return 0 to write nothing for unknown tags. | ||||
|  */ | ||||
| #define HTTPD_SSI_TAG_UNKNOWN 0xFFFF | ||||
| 
 | ||||
| #endif /* LWIP_HTTPD_SSI */ | ||||
| 
 | ||||
| #if LWIP_HTTPD_SUPPORT_POST | ||||
| 
 | ||||
| /* These functions must be implemented by the application */ | ||||
| 
 | ||||
| /** Called when a POST request has been received. The application can decide
 | ||||
|  * whether to accept it or not. | ||||
|  * | ||||
|  * @param connection Unique connection identifier, valid until httpd_post_end | ||||
|  *        is called. | ||||
|  * @param uri The HTTP header URI receiving the POST request. | ||||
|  * @param http_request The raw HTTP request (the first packet, normally). | ||||
|  * @param http_request_len Size of 'http_request'. | ||||
|  * @param content_len Content-Length from HTTP header. | ||||
|  * @param response_uri Filename of response file, to be filled when denying the | ||||
|  *        request | ||||
|  * @param response_uri_len Size of the 'response_uri' buffer. | ||||
|  * @param post_auto_wnd Set this to 0 to let the callback code handle window | ||||
|  *        updates by calling 'httpd_post_data_recved' (to throttle rx speed) | ||||
|  *        default is 1 (httpd handles window updates automatically) | ||||
|  * @return ERR_OK: Accept the POST request, data may be passed in | ||||
|  *         another err_t: Deny the POST request, send back 'bad request'. | ||||
|  */ | ||||
| err_t httpd_post_begin(void *connection, const char *uri, const char *http_request, | ||||
|                        u16_t http_request_len, int content_len, char *response_uri, | ||||
|                        u16_t response_uri_len, u8_t *post_auto_wnd); | ||||
| 
 | ||||
| /** Called for each pbuf of data that has been received for a POST.
 | ||||
|  * ATTENTION: The application is responsible for freeing the pbufs passed in! | ||||
|  * | ||||
|  * @param connection Unique connection identifier. | ||||
|  * @param p Received data. | ||||
|  * @return ERR_OK: Data accepted. | ||||
|  *         another err_t: Data denied, http_post_get_response_uri will be called. | ||||
|  */ | ||||
| err_t httpd_post_receive_data(void *connection, struct pbuf *p); | ||||
| 
 | ||||
| /** Called when all data is received or when the connection is closed.
 | ||||
|  * The application must return the filename/URI of a file to send in response | ||||
|  * to this POST request. If the response_uri buffer is untouched, a 404 | ||||
|  * response is returned. | ||||
|  * | ||||
|  * @param connection Unique connection identifier. | ||||
|  * @param response_uri Filename of response file, to be filled when denying the request | ||||
|  * @param response_uri_len Size of the 'response_uri' buffer. | ||||
|  */ | ||||
| void httpd_post_finished(void *connection, char *response_uri, u16_t response_uri_len); | ||||
| 
 | ||||
| #if LWIP_HTTPD_POST_MANUAL_WND | ||||
| void httpd_post_data_recved(void *connection, u16_t recved_len); | ||||
| #endif /* LWIP_HTTPD_POST_MANUAL_WND */ | ||||
| 
 | ||||
| #endif /* LWIP_HTTPD_SUPPORT_POST */ | ||||
| 
 | ||||
| void httpd_init(void); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HTTPD_H */ | ||||
|  | @ -0,0 +1,327 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * HTTP server options list | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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> | ||||
|  * | ||||
|  * This version of the file has been modified by Texas Instruments to offer | ||||
|  * simple server-side-include (SSI) and Common Gateway Interface (CGI) | ||||
|  * capability. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_HTTPD_OPTS_H | ||||
| #define LWIP_HDR_APPS_HTTPD_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup httpd_opts Options | ||||
|  * @ingroup httpd | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /** Set this to 1 to support CGI (old style) */ | ||||
| #if !defined LWIP_HTTPD_CGI || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_CGI            0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support CGI (new style) */ | ||||
| #if !defined LWIP_HTTPD_CGI_SSI || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_CGI_SSI        0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support SSI (Server-Side-Includes) */ | ||||
| #if !defined LWIP_HTTPD_SSI || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SSI            0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to implement an SSI tag handler callback that gets a const char*
 | ||||
|  * to the tag (instead of an index into a pre-registered array of known tags) */ | ||||
| #if !defined LWIP_HTTPD_SSI_RAW || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SSI_RAW        0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support HTTP POST */ | ||||
| #if !defined LWIP_HTTPD_SUPPORT_POST || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SUPPORT_POST   0 | ||||
| #endif | ||||
| 
 | ||||
| /* The maximum number of parameters that the CGI handler can be sent. */ | ||||
| #if !defined LWIP_HTTPD_MAX_CGI_PARAMETERS || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_MAX_CGI_PARAMETERS 16 | ||||
| #endif | ||||
| 
 | ||||
| /** LWIP_HTTPD_SSI_MULTIPART==1: SSI handler function is called with 2 more
 | ||||
|  * arguments indicating a counter for insert string that are too long to be | ||||
|  * inserted at once: the SSI handler function must then set 'next_tag_part' | ||||
|  * which will be passed back to it in the next call. */ | ||||
| #if !defined LWIP_HTTPD_SSI_MULTIPART || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SSI_MULTIPART    0 | ||||
| #endif | ||||
| 
 | ||||
| /* The maximum length of the string comprising the tag name */ | ||||
| #if !defined LWIP_HTTPD_MAX_TAG_NAME_LEN || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_MAX_TAG_NAME_LEN 8 | ||||
| #endif | ||||
| 
 | ||||
| /* The maximum length of string that can be returned to replace any given tag */ | ||||
| #if !defined LWIP_HTTPD_MAX_TAG_INSERT_LEN || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_MAX_TAG_INSERT_LEN 192 | ||||
| #endif | ||||
| 
 | ||||
| #if !defined LWIP_HTTPD_POST_MANUAL_WND || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_POST_MANUAL_WND  0 | ||||
| #endif | ||||
| 
 | ||||
| /** This string is passed in the HTTP header as "Server: " */ | ||||
| #if !defined HTTPD_SERVER_AGENT || defined __DOXYGEN__ | ||||
| #define HTTPD_SERVER_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)"
 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 if you want to include code that creates HTTP headers
 | ||||
|  * at runtime. Default is off: HTTP headers are then created statically | ||||
|  * by the makefsdata tool. Static headers mean smaller code size, but | ||||
|  * the (readonly) fsdata will grow a bit as every file includes the HTTP | ||||
|  * header. */ | ||||
| #if !defined LWIP_HTTPD_DYNAMIC_HEADERS || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_DYNAMIC_HEADERS 0 | ||||
| #endif | ||||
| 
 | ||||
| #if !defined HTTPD_DEBUG || defined __DOXYGEN__ | ||||
| #define HTTPD_DEBUG         LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to use a memp pool for allocating 
 | ||||
|  * struct http_state instead of the heap. | ||||
|  */ | ||||
| #if !defined HTTPD_USE_MEM_POOL || defined __DOXYGEN__ | ||||
| #define HTTPD_USE_MEM_POOL  0 | ||||
| #endif | ||||
| 
 | ||||
| /** The server port for HTTPD to use */ | ||||
| #if !defined HTTPD_SERVER_PORT || defined __DOXYGEN__ | ||||
| #define HTTPD_SERVER_PORT                   80 | ||||
| #endif | ||||
| 
 | ||||
| /** Maximum retries before the connection is aborted/closed.
 | ||||
|  * - number of times pcb->poll is called -> default is 4*500ms = 2s; | ||||
|  * - reset when pcb->sent is called | ||||
|  */ | ||||
| #if !defined HTTPD_MAX_RETRIES || defined __DOXYGEN__ | ||||
| #define HTTPD_MAX_RETRIES                   4 | ||||
| #endif | ||||
| 
 | ||||
| /** The poll delay is X*500ms */ | ||||
| #if !defined HTTPD_POLL_INTERVAL || defined __DOXYGEN__ | ||||
| #define HTTPD_POLL_INTERVAL                 4 | ||||
| #endif | ||||
| 
 | ||||
| /** Priority for tcp pcbs created by HTTPD (very low by default).
 | ||||
|  *  Lower priorities get killed first when running out of memory. | ||||
|  */ | ||||
| #if !defined HTTPD_TCP_PRIO || defined __DOXYGEN__ | ||||
| #define HTTPD_TCP_PRIO                      TCP_PRIO_MIN | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to enable timing each file sent */ | ||||
| #if !defined LWIP_HTTPD_TIMING || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_TIMING                   0 | ||||
| #endif | ||||
| /** Set this to 1 to enable timing each file sent */ | ||||
| #if !defined HTTPD_DEBUG_TIMING || defined __DOXYGEN__ | ||||
| #define HTTPD_DEBUG_TIMING                  LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to one to show error pages when parsing a request fails instead
 | ||||
|     of simply closing the connection. */ | ||||
| #if !defined LWIP_HTTPD_SUPPORT_EXTSTATUS || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SUPPORT_EXTSTATUS        0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 0 to drop support for HTTP/0.9 clients (to save some bytes) */ | ||||
| #if !defined LWIP_HTTPD_SUPPORT_V09 || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SUPPORT_V09              1 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to enable HTTP/1.1 persistent connections.
 | ||||
|  * ATTENTION: If the generated file system includes HTTP headers, these must | ||||
|  * include the "Connection: keep-alive" header (pass argument "-11" to makefsdata). | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_SUPPORT_11_KEEPALIVE || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SUPPORT_11_KEEPALIVE     0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support HTTP request coming in in multiple packets/pbufs */ | ||||
| #if !defined LWIP_HTTPD_SUPPORT_REQUESTLIST || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SUPPORT_REQUESTLIST      1 | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_HTTPD_SUPPORT_REQUESTLIST | ||||
| /** Number of rx pbufs to enqueue to parse an incoming request (up to the first
 | ||||
|     newline) */ | ||||
| #if !defined LWIP_HTTPD_REQ_QUEUELEN || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_REQ_QUEUELEN             5 | ||||
| #endif | ||||
| 
 | ||||
| /** Number of (TCP payload-) bytes (in pbufs) to enqueue to parse and incoming
 | ||||
|     request (up to the first double-newline) */ | ||||
| #if !defined LWIP_HTTPD_REQ_BUFSIZE || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_REQ_BUFSIZE              LWIP_HTTPD_MAX_REQ_LENGTH | ||||
| #endif | ||||
| 
 | ||||
| /** Defines the maximum length of a HTTP request line (up to the first CRLF,
 | ||||
|     copied from pbuf into this a global buffer when pbuf- or packet-queues | ||||
|     are received - otherwise the input pbuf is used directly) */ | ||||
| #if !defined LWIP_HTTPD_MAX_REQ_LENGTH || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_MAX_REQ_LENGTH           LWIP_MIN(1023, (LWIP_HTTPD_REQ_QUEUELEN * PBUF_POOL_BUFSIZE)) | ||||
| #endif | ||||
| #endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ | ||||
| 
 | ||||
| /** This is the size of a static buffer used when URIs end with '/'.
 | ||||
|  * In this buffer, the directory requested is concatenated with all the | ||||
|  * configured default file names. | ||||
|  * Set to 0 to disable checking default filenames on non-root directories. | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_MAX_REQUEST_URI_LEN || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_MAX_REQUEST_URI_LEN      63 | ||||
| #endif | ||||
| 
 | ||||
| /** Maximum length of the filename to send as response to a POST request,
 | ||||
|  * filled in by the application when a POST is finished. | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN 63 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 0 to not send the SSI tag (default is on, so the tag will
 | ||||
|  * be sent in the HTML page */ | ||||
| #if !defined LWIP_HTTPD_SSI_INCLUDE_TAG || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_SSI_INCLUDE_TAG           1 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to call tcp_abort when tcp_close fails with memory error.
 | ||||
|  * This can be used to prevent consuming all memory in situations where the | ||||
|  * HTTP server has low priority compared to other communication. */ | ||||
| #if !defined LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR  0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to kill the oldest connection when running out of
 | ||||
|  * memory for 'struct http_state' or 'struct http_ssi_state'. | ||||
|  * ATTENTION: This puts all connections on a linked list, so may be kind of slow. | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED 0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to send URIs without extension without headers
 | ||||
|  * (who uses this at all??) */ | ||||
| #if !defined LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI 0 | ||||
| #endif | ||||
| 
 | ||||
| /** Default: Tags are sent from struct http_state and are therefore volatile */ | ||||
| #if !defined HTTP_IS_TAG_VOLATILE || defined __DOXYGEN__ | ||||
| #define HTTP_IS_TAG_VOLATILE(ptr) TCP_WRITE_FLAG_COPY | ||||
| #endif | ||||
| 
 | ||||
| /* By default, the httpd is limited to send 2*pcb->mss to keep resource usage low
 | ||||
|    when http is not an important protocol in the device. */ | ||||
| #if !defined HTTPD_LIMIT_SENDING_TO_2MSS || defined __DOXYGEN__ | ||||
| #define HTTPD_LIMIT_SENDING_TO_2MSS 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Define this to a function that returns the maximum amount of data to enqueue.
 | ||||
|    The function have this signature: u16_t fn(struct tcp_pcb* pcb); */ | ||||
| #if !defined HTTPD_MAX_WRITE_LEN || defined __DOXYGEN__ | ||||
| #if HTTPD_LIMIT_SENDING_TO_2MSS | ||||
| #define HTTPD_MAX_WRITE_LEN(pcb)    (2 * tcp_mss(pcb)) | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| /*------------------- FS OPTIONS -------------------*/ | ||||
| 
 | ||||
| /** Set this to 1 and provide the functions:
 | ||||
|  * - "int fs_open_custom(struct fs_file *file, const char *name)" | ||||
|  *    Called first for every opened file to allow opening files | ||||
|  *    that are not included in fsdata(_custom).c | ||||
|  * - "void fs_close_custom(struct fs_file *file)" | ||||
|  *    Called to free resources allocated by fs_open_custom(). | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_CUSTOM_FILES || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_CUSTOM_FILES       0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support fs_read() to dynamically read file data.
 | ||||
|  * Without this (default=off), only one-block files are supported, | ||||
|  * and the contents must be ready after fs_open(). | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_DYNAMIC_FILE_READ || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_DYNAMIC_FILE_READ  0 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to include an application state argument per file
 | ||||
|  * that is opened. This allows to keep a state per connection/file. | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_FILE_STATE || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_FILE_STATE         0 | ||||
| #endif | ||||
| 
 | ||||
| /** HTTPD_PRECALCULATED_CHECKSUM==1: include precompiled checksums for
 | ||||
|  * predefined (MSS-sized) chunks of the files to prevent having to calculate | ||||
|  * the checksums at runtime. */ | ||||
| #if !defined HTTPD_PRECALCULATED_CHECKSUM || defined __DOXYGEN__ | ||||
| #define HTTPD_PRECALCULATED_CHECKSUM  0 | ||||
| #endif | ||||
| 
 | ||||
| /** LWIP_HTTPD_FS_ASYNC_READ==1: support asynchronous read operations
 | ||||
|  * (fs_read_async returns FS_READ_DELAYED and calls a callback when finished). | ||||
|  */ | ||||
| #if !defined LWIP_HTTPD_FS_ASYNC_READ || defined __DOXYGEN__ | ||||
| #define LWIP_HTTPD_FS_ASYNC_READ      0 | ||||
| #endif | ||||
| 
 | ||||
| /** Filename (including path) to use as FS data file */ | ||||
| #if !defined HTTPD_FSDATA_FILE || defined __DOXYGEN__ | ||||
| /* HTTPD_USE_CUSTOM_FSDATA: Compatibility with deprecated lwIP option */ | ||||
| #if defined(HTTPD_USE_CUSTOM_FSDATA) && (HTTPD_USE_CUSTOM_FSDATA != 0) | ||||
| #define HTTPD_FSDATA_FILE "fsdata_custom.c" | ||||
| #else | ||||
| #define HTTPD_FSDATA_FILE "fsdata.c" | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_HTTPD_OPTS_H */ | ||||
|  | @ -0,0 +1,84 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * lwIP iPerf server implementation | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_LWIPERF_H | ||||
| #define LWIP_HDR_APPS_LWIPERF_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| #include "lwip/ip_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define LWIPERF_TCP_PORT_DEFAULT  5001 | ||||
| 
 | ||||
| /** lwIPerf test results */ | ||||
| enum lwiperf_report_type | ||||
| { | ||||
|   /** The server side test is done */ | ||||
|   LWIPERF_TCP_DONE_SERVER, | ||||
|   /** The client side test is done */ | ||||
|   LWIPERF_TCP_DONE_CLIENT, | ||||
|   /** Local error lead to test abort */ | ||||
|   LWIPERF_TCP_ABORTED_LOCAL, | ||||
|   /** Data check error lead to test abort */ | ||||
|   LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, | ||||
|   /** Transmit error lead to test abort */ | ||||
|   LWIPERF_TCP_ABORTED_LOCAL_TXERROR, | ||||
|   /** Remote side aborted the test */ | ||||
|   LWIPERF_TCP_ABORTED_REMOTE | ||||
| }; | ||||
| 
 | ||||
| /** Prototype of a report function that is called when a session is finished.
 | ||||
|     This report function can show the test results. | ||||
|     @param report_type contains the test result */ | ||||
| typedef void (*lwiperf_report_fn)(void *arg, enum lwiperf_report_type report_type, | ||||
|   const ip_addr_t* local_addr, u16_t local_port, const ip_addr_t* remote_addr, u16_t remote_port, | ||||
|   u32_t bytes_transferred, u32_t ms_duration, u32_t bandwidth_kbitpsec); | ||||
| 
 | ||||
| 
 | ||||
| void* lwiperf_start_tcp_server(const ip_addr_t* local_addr, u16_t local_port, | ||||
|                                lwiperf_report_fn report_fn, void* report_arg); | ||||
| void* lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void* report_arg); | ||||
| void  lwiperf_abort(void* lwiperf_session); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_LWIPERF_H */ | ||||
|  | @ -0,0 +1,69 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MDNS responder | ||||
|  */ | ||||
| 
 | ||||
|  /*
 | ||||
|  * Copyright (c) 2015 Verisure Innovation AB | ||||
|  * 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: Erik Ekman <erik@kryo.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_MDNS_H | ||||
| #define LWIP_HDR_MDNS_H | ||||
| 
 | ||||
| #include "lwip/apps/mdns_opts.h" | ||||
| #include "lwip/netif.h" | ||||
| 
 | ||||
| #if LWIP_MDNS_RESPONDER | ||||
| 
 | ||||
| enum mdns_sd_proto { | ||||
|   DNSSD_PROTO_UDP = 0, | ||||
|   DNSSD_PROTO_TCP = 1 | ||||
| }; | ||||
| 
 | ||||
| #define MDNS_LABEL_MAXLEN  63 | ||||
| 
 | ||||
| struct mdns_host; | ||||
| struct mdns_service; | ||||
| 
 | ||||
| /** Callback function to add text to a reply, called when generating the reply */ | ||||
| typedef void (*service_get_txt_fn_t)(struct mdns_service *service, void *txt_userdata); | ||||
| 
 | ||||
| void mdns_resp_init(void); | ||||
| 
 | ||||
| err_t mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl); | ||||
| err_t mdns_resp_remove_netif(struct netif *netif); | ||||
| 
 | ||||
| err_t mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_userdata); | ||||
| err_t mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len); | ||||
| void mdns_resp_netif_settings_changed(struct netif *netif); | ||||
| 
 | ||||
| #endif /* LWIP_MDNS_RESPONDER */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_MDNS_H */ | ||||
|  | @ -0,0 +1,74 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MDNS responder | ||||
|  */ | ||||
| 
 | ||||
|  /*
 | ||||
|  * Copyright (c) 2015 Verisure Innovation AB | ||||
|  * 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: Erik Ekman <erik@kryo.se> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_MDNS_OPTS_H | ||||
| #define LWIP_HDR_APPS_MDNS_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup mdns_opts Options | ||||
|  * @ingroup mdns | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * LWIP_MDNS_RESPONDER==1: Turn on multicast DNS module. UDP must be available for MDNS | ||||
|  * transport. IGMP is needed for IPv4 multicast. | ||||
|  */ | ||||
| #ifndef LWIP_MDNS_RESPONDER | ||||
| #define LWIP_MDNS_RESPONDER             1 | ||||
| #endif /* LWIP_MDNS_RESPONDER */ | ||||
| 
 | ||||
| /** The maximum number of services per netif */ | ||||
| #ifndef MDNS_MAX_SERVICES | ||||
| #define MDNS_MAX_SERVICES               1 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * MDNS_DEBUG: Enable debugging for multicast DNS. | ||||
|  */ | ||||
| #ifndef MDNS_DEBUG | ||||
| #define MDNS_DEBUG                       LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_MDNS_OPTS_H */ | ||||
| 
 | ||||
|  | @ -0,0 +1,66 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MDNS responder private definitions | ||||
|  */ | ||||
| 
 | ||||
|  /*
 | ||||
|  * Copyright (c) 2015 Verisure Innovation AB | ||||
|  * 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: Erik Ekman <erik@kryo.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_MDNS_PRIV_H | ||||
| #define LWIP_HDR_MDNS_PRIV_H | ||||
| 
 | ||||
| #include "lwip/apps/mdns_opts.h" | ||||
| #include "lwip/pbuf.h" | ||||
| 
 | ||||
| #if LWIP_MDNS_RESPONDER | ||||
| 
 | ||||
| /* Domain struct and methods - visible for unit tests */ | ||||
| 
 | ||||
| #define MDNS_DOMAIN_MAXLEN 256 | ||||
| #define MDNS_READNAME_ERROR 0xFFFF | ||||
| 
 | ||||
| struct mdns_domain { | ||||
|   /* Encoded domain name */ | ||||
|   u8_t name[MDNS_DOMAIN_MAXLEN]; | ||||
|   /* Total length of domain name, including zero */ | ||||
|   u16_t length; | ||||
|   /* Set if compression of this domain is not allowed */ | ||||
|   u8_t skip_compression; | ||||
| }; | ||||
| 
 | ||||
| err_t mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len); | ||||
| u16_t mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain); | ||||
| int mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b); | ||||
| u16_t mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain); | ||||
| 
 | ||||
| #endif /* LWIP_MDNS_RESPONDER */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_MDNS_PRIV_H */ | ||||
|  | @ -0,0 +1,243 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MQTT client | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (c) 2016 Erik Andersson | ||||
|  * 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: Erik Andersson | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_MQTT_CLIENT_H | ||||
| #define LWIP_HDR_APPS_MQTT_CLIENT_H | ||||
| 
 | ||||
| #include "lwip/apps/mqtt_opts.h" | ||||
| #include "lwip/err.h" | ||||
| 
 | ||||
| #ifdef	__cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef struct mqtt_client_t mqtt_client_t; | ||||
| 
 | ||||
| /** @ingroup mqtt
 | ||||
|  * Default MQTT port */ | ||||
| #define MQTT_PORT 1883 | ||||
| 
 | ||||
| /*---------------------------------------------------------------------------------------------- */ | ||||
| /* Connection with server */ | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup mqtt | ||||
|  * Client information and connection parameters */ | ||||
| struct mqtt_connect_client_info_t { | ||||
|   /** Client identifier, must be set by caller */ | ||||
|   const char *client_id; | ||||
|   /** User name and password, set to NULL if not used */ | ||||
|   const char* client_user; | ||||
|   const char* client_pass; | ||||
|   /** keep alive time in seconds, 0 to disable keep alive functionality*/ | ||||
|   u16_t keep_alive; | ||||
|   /** will topic, set to NULL if will is not to be used,
 | ||||
|       will_msg, will_qos and will retain are then ignored */ | ||||
|   const char* will_topic; | ||||
|   const char* will_msg; | ||||
|   u8_t will_qos; | ||||
|   u8_t will_retain; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup mqtt | ||||
|  * Connection status codes */ | ||||
| typedef enum | ||||
| { | ||||
|   MQTT_CONNECT_ACCEPTED                 = 0, | ||||
|   MQTT_CONNECT_REFUSED_PROTOCOL_VERSION = 1, | ||||
|   MQTT_CONNECT_REFUSED_IDENTIFIER       = 2, | ||||
|   MQTT_CONNECT_REFUSED_SERVER           = 3, | ||||
|   MQTT_CONNECT_REFUSED_USERNAME_PASS    = 4, | ||||
|   MQTT_CONNECT_REFUSED_NOT_AUTHORIZED_  = 5, | ||||
|   MQTT_CONNECT_DISCONNECTED             = 256, | ||||
|   MQTT_CONNECT_TIMEOUT                  = 257 | ||||
| } mqtt_connection_status_t; | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup mqtt | ||||
|  * Function prototype for mqtt connection status callback. Called when | ||||
|  * client has connected to the server after initiating a mqtt connection attempt by | ||||
|  * calling mqtt_connect() or when connection is closed by server or an error | ||||
|  * | ||||
|  * @param client MQTT client itself | ||||
|  * @param arg Additional argument to pass to the callback function | ||||
|  * @param status Connect result code or disconnection notification @see mqtt_connection_status_t | ||||
|  * | ||||
|  */ | ||||
| typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup mqtt | ||||
|  * Data callback flags */ | ||||
| enum { | ||||
|   /** Flag set when last fragment of data arrives in data callback */ | ||||
|   MQTT_DATA_FLAG_LAST = 1 | ||||
| }; | ||||
| 
 | ||||
| /** 
 | ||||
|  * @ingroup mqtt | ||||
|  * Function prototype for MQTT incoming publish data callback function. Called when data | ||||
|  * arrives to a subscribed topic @see mqtt_subscribe | ||||
|  * | ||||
|  * @param arg Additional argument to pass to the callback function | ||||
|  * @param data User data, pointed object, data may not be referenced after callback return, | ||||
|           NULL is passed when all publish data are delivered | ||||
|  * @param len Length of publish data fragment | ||||
|  * @param flags MQTT_DATA_FLAG_LAST set when this call contains the last part of data from publish message | ||||
|  * | ||||
|  */ | ||||
| typedef void (*mqtt_incoming_data_cb_t)(void *arg, const u8_t *data, u16_t len, u8_t flags); | ||||
| 
 | ||||
| 
 | ||||
| /** 
 | ||||
|  * @ingroup mqtt | ||||
|  * Function prototype for MQTT incoming publish function. Called when an incoming publish | ||||
|  * arrives to a subscribed topic @see mqtt_subscribe | ||||
|  * | ||||
|  * @param arg Additional argument to pass to the callback function | ||||
|  * @param topic Zero terminated Topic text string, topic may not be referenced after callback return | ||||
|  * @param tot_len Total length of publish data, if set to 0 (no publish payload) data callback will not be invoked | ||||
|  */ | ||||
| typedef void (*mqtt_incoming_publish_cb_t)(void *arg, const char *topic, u32_t tot_len); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup mqtt | ||||
|  * Function prototype for mqtt request callback. Called when a subscribe, unsubscribe | ||||
|  * or publish request has completed | ||||
|  * @param arg Pointer to user data supplied when invoking request | ||||
|  * @param err ERR_OK on success | ||||
|  *            ERR_TIMEOUT if no response was received within timeout, | ||||
|  *            ERR_ABRT if (un)subscribe was denied | ||||
|  */ | ||||
| typedef void (*mqtt_request_cb_t)(void *arg, err_t err); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Pending request item, binds application callback to pending server requests | ||||
|  */ | ||||
| struct mqtt_request_t | ||||
| { | ||||
|   /** Next item in list, NULL means this is the last in chain,
 | ||||
|       next pointing at itself means request is unallocated */ | ||||
|   struct mqtt_request_t *next; | ||||
|   /** Callback to upper layer */ | ||||
|   mqtt_request_cb_t cb; | ||||
|   void *arg; | ||||
|   /** MQTT packet identifier */ | ||||
|   u16_t pkt_id; | ||||
|   /** Expire time relative to element before this  */ | ||||
|   u16_t timeout_diff; | ||||
| }; | ||||
| 
 | ||||
| /** Ring buffer */ | ||||
| struct mqtt_ringbuf_t { | ||||
|   u16_t put; | ||||
|   u16_t get; | ||||
|   u8_t buf[MQTT_OUTPUT_RINGBUF_SIZE]; | ||||
| }; | ||||
| 
 | ||||
| /** MQTT client */ | ||||
| struct mqtt_client_t | ||||
| { | ||||
|   /** Timers and timeouts */ | ||||
|   u16_t cyclic_tick; | ||||
|   u16_t keep_alive; | ||||
|   u16_t server_watchdog; | ||||
|   /** Packet identifier generator*/ | ||||
|   u16_t pkt_id_seq; | ||||
|   /** Packet identifier of pending incoming publish */ | ||||
|   u16_t inpub_pkt_id; | ||||
|   /** Connection state */ | ||||
|   u8_t conn_state; | ||||
|   struct tcp_pcb *conn; | ||||
|   /** Connection callback */ | ||||
|   void *connect_arg; | ||||
|   mqtt_connection_cb_t connect_cb; | ||||
|   /** Pending requests to server */ | ||||
|   struct mqtt_request_t *pend_req_queue; | ||||
|   struct mqtt_request_t req_list[MQTT_REQ_MAX_IN_FLIGHT]; | ||||
|   void *inpub_arg; | ||||
|   /** Incoming data callback */ | ||||
|   mqtt_incoming_data_cb_t data_cb; | ||||
|   mqtt_incoming_publish_cb_t pub_cb; | ||||
|   /** Input */ | ||||
|   u32_t msg_idx; | ||||
|   u8_t rx_buffer[MQTT_VAR_HEADER_BUFFER_LEN]; | ||||
|   /** Output ring-buffer */ | ||||
|   struct mqtt_ringbuf_t output; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /** Connect to server */ | ||||
| err_t mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ipaddr, u16_t port, mqtt_connection_cb_t cb, void *arg, | ||||
|                    const struct mqtt_connect_client_info_t *client_info); | ||||
| 
 | ||||
| /** Disconnect from server */ | ||||
| void mqtt_disconnect(mqtt_client_t *client); | ||||
| 
 | ||||
| /** Create new client */ | ||||
| mqtt_client_t *mqtt_client_new(void); | ||||
| 
 | ||||
| /** Check connection status */ | ||||
| u8_t mqtt_client_is_connected(mqtt_client_t *client); | ||||
| 
 | ||||
| /** Set callback to call for incoming publish */ | ||||
| void mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t, | ||||
|                              mqtt_incoming_data_cb_t data_cb, void *arg); | ||||
| 
 | ||||
| /** Common function for subscribe and unsubscribe */ | ||||
| err_t mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub); | ||||
| 
 | ||||
| /** @ingroup mqtt
 | ||||
|  *Subscribe to topic */ | ||||
| #define mqtt_subscribe(client, topic, qos, cb, arg) mqtt_sub_unsub(client, topic, qos, cb, arg, 1) | ||||
| /** @ingroup mqtt
 | ||||
|  *  Unsubscribe to topic */ | ||||
| #define mqtt_unsubscribe(client, topic, cb, arg) mqtt_sub_unsub(client, topic, 0, cb, arg, 0) | ||||
| 
 | ||||
| 
 | ||||
| /** Publish data to topic */ | ||||
| err_t mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, | ||||
|                                     mqtt_request_cb_t cb, void *arg); | ||||
| 
 | ||||
| #ifdef	__cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_MQTT_CLIENT_H */ | ||||
|  | @ -0,0 +1,103 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MQTT client options | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (c) 2016 Erik Andersson | ||||
|  * 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: Erik Andersson | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_MQTT_OPTS_H | ||||
| #define LWIP_HDR_APPS_MQTT_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| #ifdef	__cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup mqtt_opts Options | ||||
|  * @ingroup mqtt | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Output ring-buffer size, must be able to fit largest outgoing publish message topic+payloads | ||||
|  */ | ||||
| #ifndef MQTT_OUTPUT_RINGBUF_SIZE | ||||
| #define MQTT_OUTPUT_RINGBUF_SIZE 256 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Number of bytes in receive buffer, must be at least the size of the longest incoming topic + 8 | ||||
|  * If one wants to avoid fragmented incoming publish, set length to max incoming topic length + max payload length + 8 | ||||
|  */ | ||||
| #ifndef MQTT_VAR_HEADER_BUFFER_LEN | ||||
| #define MQTT_VAR_HEADER_BUFFER_LEN 128 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Maximum number of pending subscribe, unsubscribe and publish requests to server . | ||||
|  */ | ||||
| #ifndef MQTT_REQ_MAX_IN_FLIGHT | ||||
| #define MQTT_REQ_MAX_IN_FLIGHT 4 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Seconds between each cyclic timer call. | ||||
|  */ | ||||
| #ifndef MQTT_CYCLIC_TIMER_INTERVAL | ||||
| #define MQTT_CYCLIC_TIMER_INTERVAL 5 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Publish, subscribe and unsubscribe request timeout in seconds. | ||||
|  */ | ||||
| #ifndef MQTT_REQ_TIMEOUT | ||||
| #define MQTT_REQ_TIMEOUT 30 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Seconds for MQTT connect response timeout after sending connect request | ||||
|  */ | ||||
| #ifndef MQTT_CONNECT_TIMOUT | ||||
| #define MQTT_CONNECT_TIMOUT 100 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_MQTT_OPTS_H */ | ||||
|  | @ -0,0 +1,43 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * NETBIOS name service responder | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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. | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_NETBIOS_H | ||||
| #define LWIP_HDR_APPS_NETBIOS_H | ||||
| 
 | ||||
| #include "lwip/apps/netbiosns_opts.h" | ||||
| 
 | ||||
| void netbiosns_init(void); | ||||
| #ifndef NETBIOS_LWIP_NAME | ||||
| void netbiosns_set_name(const char* hostname); | ||||
| #endif | ||||
| void netbiosns_stop(void); | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_NETBIOS_H */ | ||||
|  | @ -0,0 +1,59 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * NETBIOS name service responder options | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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. | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_NETBIOS_OPTS_H | ||||
| #define LWIP_HDR_APPS_NETBIOS_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup netbiosns_opts Options | ||||
|  * @ingroup netbiosns | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /** NetBIOS name of lwip device
 | ||||
|  * This must be uppercase until NETBIOS_STRCMP() is defined to a string | ||||
|  * comparision function that is case insensitive. | ||||
|  * If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME): | ||||
|  * (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "") | ||||
|  * | ||||
|  * If this is not defined, netbiosns_set_name() can be called at runtime to change the name. | ||||
|  */ | ||||
| #ifdef __DOXYGEN__ | ||||
| #define NETBIOS_LWIP_NAME "NETBIOSLWIPDEV" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_NETBIOS_OPTS_H */ | ||||
|  | @ -0,0 +1,128 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP server main API - start and basic configuration | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv> | ||||
|  * Copyright (c) 2001, 2002 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. | ||||
|  * | ||||
|  * This file is part of the lwIP TCP/IP stack. | ||||
|  * | ||||
|  * Author: Leon Woestenberg <leon.woestenberg@axon.tv> | ||||
|  *         Martin Hentschel <info@cl-soft.de> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_SNMP_H | ||||
| #define LWIP_HDR_APPS_SNMP_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| 
 | ||||
| #include "lwip/err.h" | ||||
| #include "lwip/apps/snmp_core.h" | ||||
| 
 | ||||
| /** SNMP variable binding descriptor (publically needed for traps) */ | ||||
| struct snmp_varbind | ||||
| { | ||||
|   /** pointer to next varbind, NULL for last in list */ | ||||
|   struct snmp_varbind *next; | ||||
|   /** pointer to previous varbind, NULL for first in list */ | ||||
|   struct snmp_varbind *prev; | ||||
| 
 | ||||
|   /** object identifier */ | ||||
|   struct snmp_obj_id oid; | ||||
| 
 | ||||
|   /** value ASN1 type */ | ||||
|   u8_t type; | ||||
|   /** object value length */ | ||||
|   u16_t value_len; | ||||
|   /** object value */ | ||||
|   void *value; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup snmp_core | ||||
|  * Agent setup, start listening to port 161. | ||||
|  */ | ||||
| void snmp_init(void); | ||||
| void snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs); | ||||
| 
 | ||||
| void snmp_set_device_enterprise_oid(const struct snmp_obj_id* device_enterprise_oid); | ||||
| const struct snmp_obj_id* snmp_get_device_enterprise_oid(void); | ||||
| 
 | ||||
| void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); | ||||
| void snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst); | ||||
| 
 | ||||
| /** Generic trap: cold start */ | ||||
| #define SNMP_GENTRAP_COLDSTART 0 | ||||
| /** Generic trap: warm start */ | ||||
| #define SNMP_GENTRAP_WARMSTART 1 | ||||
| /** Generic trap: link down */ | ||||
| #define SNMP_GENTRAP_LINKDOWN 2 | ||||
| /** Generic trap: link up */ | ||||
| #define SNMP_GENTRAP_LINKUP 3 | ||||
| /** Generic trap: authentication failure */ | ||||
| #define SNMP_GENTRAP_AUTH_FAILURE 4 | ||||
| /** Generic trap: EGP neighbor lost */ | ||||
| #define SNMP_GENTRAP_EGP_NEIGHBOR_LOSS 5 | ||||
| /** Generic trap: enterprise specific */ | ||||
| #define SNMP_GENTRAP_ENTERPRISE_SPECIFIC 6 | ||||
| 
 | ||||
| err_t snmp_send_trap_generic(s32_t generic_trap); | ||||
| err_t snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds); | ||||
| err_t snmp_send_trap(const struct snmp_obj_id* oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds); | ||||
| 
 | ||||
| #define SNMP_AUTH_TRAPS_DISABLED 0 | ||||
| #define SNMP_AUTH_TRAPS_ENABLED  1 | ||||
| void snmp_set_auth_traps_enabled(u8_t enable); | ||||
| u8_t snmp_get_auth_traps_enabled(void); | ||||
| 
 | ||||
| const char * snmp_get_community(void); | ||||
| const char * snmp_get_community_write(void); | ||||
| const char * snmp_get_community_trap(void); | ||||
| void snmp_set_community(const char * const community); | ||||
| void snmp_set_community_write(const char * const community); | ||||
| void snmp_set_community_trap(const char * const community); | ||||
| 
 | ||||
| void snmp_coldstart_trap(void); | ||||
| void snmp_authfail_trap(void); | ||||
| 
 | ||||
| typedef void (*snmp_write_callback_fct)(const u32_t* oid, u8_t oid_len, void* callback_arg); | ||||
| void snmp_set_write_callback(snmp_write_callback_fct write_callback, void* callback_arg); | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_H */ | ||||
|  | @ -0,0 +1,364 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP core API for implementing MIBs | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_SNMP_CORE_H | ||||
| #define LWIP_HDR_APPS_SNMP_CORE_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| 
 | ||||
| #include "lwip/ip_addr.h" | ||||
| #include "lwip/err.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* basic ASN1 defines */ | ||||
| #define SNMP_ASN1_CLASS_UNIVERSAL   0x00 | ||||
| #define SNMP_ASN1_CLASS_APPLICATION 0x40 | ||||
| #define SNMP_ASN1_CLASS_CONTEXT     0x80 | ||||
| #define SNMP_ASN1_CLASS_PRIVATE     0xC0 | ||||
| 
 | ||||
| #define SNMP_ASN1_CONTENTTYPE_PRIMITIVE   0x00 | ||||
| #define SNMP_ASN1_CONTENTTYPE_CONSTRUCTED 0x20 | ||||
| 
 | ||||
| /* universal tags (from ASN.1 spec.) */ | ||||
| #define SNMP_ASN1_UNIVERSAL_END_OF_CONTENT  0 | ||||
| #define SNMP_ASN1_UNIVERSAL_INTEGER         2 | ||||
| #define SNMP_ASN1_UNIVERSAL_OCTET_STRING    4 | ||||
| #define SNMP_ASN1_UNIVERSAL_NULL            5 | ||||
| #define SNMP_ASN1_UNIVERSAL_OBJECT_ID       6 | ||||
| #define SNMP_ASN1_UNIVERSAL_SEQUENCE_OF    16 | ||||
| 
 | ||||
| /* application specific (SNMP) tags (from SNMPv2-SMI) */ | ||||
| #define SNMP_ASN1_APPLICATION_IPADDR    0  /* [APPLICATION 0] IMPLICIT OCTET STRING (SIZE (4)) */ | ||||
| #define SNMP_ASN1_APPLICATION_COUNTER   1  /* [APPLICATION 1] IMPLICIT INTEGER (0..4294967295) => u32_t */ | ||||
| #define SNMP_ASN1_APPLICATION_GAUGE     2  /* [APPLICATION 2] IMPLICIT INTEGER (0..4294967295) => u32_t */ | ||||
| #define SNMP_ASN1_APPLICATION_TIMETICKS 3  /* [APPLICATION 3] IMPLICIT INTEGER (0..4294967295) => u32_t */ | ||||
| #define SNMP_ASN1_APPLICATION_OPAQUE    4  /* [APPLICATION 4] IMPLICIT OCTET STRING */ | ||||
| #define SNMP_ASN1_APPLICATION_COUNTER64 6  /* [APPLICATION 6] IMPLICIT INTEGER (0..18446744073709551615) */ | ||||
| 
 | ||||
| /* context specific (SNMP) tags (from RFC 1905) */ | ||||
| #define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE 1 | ||||
| 
 | ||||
| /* full ASN1 type defines */ | ||||
| #define SNMP_ASN1_TYPE_END_OF_CONTENT (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_END_OF_CONTENT) | ||||
| #define SNMP_ASN1_TYPE_INTEGER        (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_INTEGER) | ||||
| #define SNMP_ASN1_TYPE_OCTET_STRING   (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OCTET_STRING) | ||||
| #define SNMP_ASN1_TYPE_NULL           (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_NULL) | ||||
| #define SNMP_ASN1_TYPE_OBJECT_ID      (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_UNIVERSAL_OBJECT_ID) | ||||
| #define SNMP_ASN1_TYPE_SEQUENCE       (SNMP_ASN1_CLASS_UNIVERSAL | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_UNIVERSAL_SEQUENCE_OF) | ||||
| #define SNMP_ASN1_TYPE_IPADDR         (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_IPADDR) | ||||
| #define SNMP_ASN1_TYPE_IPADDRESS      SNMP_ASN1_TYPE_IPADDR | ||||
| #define SNMP_ASN1_TYPE_COUNTER        (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER) | ||||
| #define SNMP_ASN1_TYPE_COUNTER32      SNMP_ASN1_TYPE_COUNTER | ||||
| #define SNMP_ASN1_TYPE_GAUGE          (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_GAUGE) | ||||
| #define SNMP_ASN1_TYPE_GAUGE32        SNMP_ASN1_TYPE_GAUGE | ||||
| #define SNMP_ASN1_TYPE_UNSIGNED32     SNMP_ASN1_TYPE_GAUGE | ||||
| #define SNMP_ASN1_TYPE_TIMETICKS      (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_TIMETICKS) | ||||
| #define SNMP_ASN1_TYPE_OPAQUE         (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_OPAQUE) | ||||
| #define SNMP_ASN1_TYPE_COUNTER64      (SNMP_ASN1_CLASS_APPLICATION | SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_APPLICATION_COUNTER64) | ||||
| 
 | ||||
| #define SNMP_VARBIND_EXCEPTION_OFFSET 0xF0 | ||||
| #define SNMP_VARBIND_EXCEPTION_MASK   0x0F | ||||
| 
 | ||||
| /** error codes predefined by SNMP prot. */ | ||||
| typedef enum { | ||||
|   SNMP_ERR_NOERROR             = 0, | ||||
| /* 
 | ||||
| outdated v1 error codes. do not use anmore! | ||||
| #define SNMP_ERR_NOSUCHNAME 2  use SNMP_ERR_NOSUCHINSTANCE instead | ||||
| #define SNMP_ERR_BADVALUE   3  use SNMP_ERR_WRONGTYPE,SNMP_ERR_WRONGLENGTH,SNMP_ERR_WRONGENCODING or SNMP_ERR_WRONGVALUE instead | ||||
| #define SNMP_ERR_READONLY   4  use SNMP_ERR_NOTWRITABLE instead | ||||
| */ | ||||
|   SNMP_ERR_GENERROR            = 5, | ||||
|   SNMP_ERR_NOACCESS            = 6, | ||||
|   SNMP_ERR_WRONGTYPE           = 7, | ||||
|   SNMP_ERR_WRONGLENGTH         = 8, | ||||
|   SNMP_ERR_WRONGENCODING       = 9, | ||||
|   SNMP_ERR_WRONGVALUE          = 10, | ||||
|   SNMP_ERR_NOCREATION          = 11, | ||||
|   SNMP_ERR_INCONSISTENTVALUE   = 12, | ||||
|   SNMP_ERR_RESOURCEUNAVAILABLE = 13, | ||||
|   SNMP_ERR_COMMITFAILED        = 14, | ||||
|   SNMP_ERR_UNDOFAILED          = 15, | ||||
|   SNMP_ERR_NOTWRITABLE         = 17, | ||||
|   SNMP_ERR_INCONSISTENTNAME    = 18, | ||||
| 
 | ||||
|   SNMP_ERR_NOSUCHINSTANCE      = SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_INSTANCE | ||||
| } snmp_err_t; | ||||
| 
 | ||||
| /** internal object identifier representation */ | ||||
| struct snmp_obj_id | ||||
| { | ||||
|   u8_t len; | ||||
|   u32_t id[SNMP_MAX_OBJ_ID_LEN]; | ||||
| }; | ||||
| 
 | ||||
| struct snmp_obj_id_const_ref | ||||
| { | ||||
|   u8_t len; | ||||
|   const u32_t* id; | ||||
| }; | ||||
| 
 | ||||
| extern const struct snmp_obj_id_const_ref snmp_zero_dot_zero; /* administrative identifier from SNMPv2-SMI */ | ||||
| 
 | ||||
| /** SNMP variant value, used as reference in struct snmp_node_instance and table implementation */ | ||||
| union snmp_variant_value | ||||
| { | ||||
|   void* ptr; | ||||
|   const void* const_ptr; | ||||
|   u32_t u32; | ||||
|   s32_t s32; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
| SNMP MIB node types | ||||
|  tree node is the only node the stack can process in order to walk the tree, | ||||
|  all other nodes are assumed to be leaf nodes. | ||||
|  This cannot be an enum because users may want to define their own node types. | ||||
| */ | ||||
| #define SNMP_NODE_TREE         0x00 | ||||
| /* predefined leaf node types */ | ||||
| #define SNMP_NODE_SCALAR       0x01 | ||||
| #define SNMP_NODE_SCALAR_ARRAY 0x02 | ||||
| #define SNMP_NODE_TABLE        0x03 | ||||
| #define SNMP_NODE_THREADSYNC   0x04 | ||||
| 
 | ||||
| /** node "base class" layout, the mandatory fields for a node  */ | ||||
| struct snmp_node | ||||
| { | ||||
|   /** one out of SNMP_NODE_TREE or any leaf node type (like SNMP_NODE_SCALAR) */ | ||||
|   u8_t node_type; | ||||
|   /** the number assigned to this node which used as part of the full OID */ | ||||
|   u32_t oid; | ||||
| }; | ||||
| 
 | ||||
| /** SNMP node instance access types */ | ||||
| typedef enum { | ||||
|   SNMP_NODE_INSTANCE_ACCESS_READ    = 1, | ||||
|   SNMP_NODE_INSTANCE_ACCESS_WRITE   = 2, | ||||
|   SNMP_NODE_INSTANCE_READ_ONLY      = SNMP_NODE_INSTANCE_ACCESS_READ, | ||||
|   SNMP_NODE_INSTANCE_READ_WRITE     = (SNMP_NODE_INSTANCE_ACCESS_READ | SNMP_NODE_INSTANCE_ACCESS_WRITE), | ||||
|   SNMP_NODE_INSTANCE_WRITE_ONLY     = SNMP_NODE_INSTANCE_ACCESS_WRITE, | ||||
|   SNMP_NODE_INSTANCE_NOT_ACCESSIBLE = 0 | ||||
| } snmp_access_t; | ||||
| 
 | ||||
| struct snmp_node_instance; | ||||
| 
 | ||||
| typedef s16_t (*node_instance_get_value_method)(struct snmp_node_instance*, void*); | ||||
| typedef snmp_err_t (*node_instance_set_test_method)(struct snmp_node_instance*, u16_t, void*); | ||||
| typedef snmp_err_t (*node_instance_set_value_method)(struct snmp_node_instance*, u16_t, void*); | ||||
| typedef void (*node_instance_release_method)(struct snmp_node_instance*); | ||||
| 
 | ||||
| #define SNMP_GET_VALUE_RAW_DATA 0x8000 | ||||
| 
 | ||||
| /** SNMP node instance */ | ||||
| struct snmp_node_instance | ||||
| { | ||||
|   /** prefilled with the node, get_instance() is called on; may be changed by user to any value to pass an arbitrary node between calls to get_instance() and get_value/test_value/set_value */ | ||||
|   const struct snmp_node* node; | ||||
|   /** prefilled with the instance id requested; for get_instance() this is the exact oid requested; for get_next_instance() this is the relative starting point, stack expects relative oid of next node here */ | ||||
|   struct snmp_obj_id instance_oid; | ||||
| 
 | ||||
|   /** ASN type for this object (see snmp_asn1.h for definitions) */ | ||||
|   u8_t asn1_type; | ||||
|   /** one out of instance access types defined above (SNMP_NODE_INSTANCE_READ_ONLY,...) */ | ||||
|   snmp_access_t access; | ||||
| 
 | ||||
|   /** returns object value for the given object identifier. Return values <0 to indicate an error */ | ||||
|   node_instance_get_value_method get_value; | ||||
|   /** tests length and/or range BEFORE setting */ | ||||
|   node_instance_set_test_method set_test; | ||||
|   /** sets object value, only called when set_test() was successful */ | ||||
|   node_instance_set_value_method set_value; | ||||
|   /** called in any case when the instance is not required anymore by stack (useful for freeing memory allocated in get_instance/get_next_instance methods) */ | ||||
|   node_instance_release_method release_instance; | ||||
| 
 | ||||
|   /** reference to pass arbitrary value between calls to get_instance() and get_value/test_value/set_value */ | ||||
|   union snmp_variant_value reference; | ||||
|   /** see reference (if reference is a pointer, the length of underlying data may be stored here or anything else) */ | ||||
|   u32_t reference_len; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /** SNMP tree node */ | ||||
| struct snmp_tree_node | ||||
| { | ||||
|   /** inherited "base class" members */ | ||||
|   struct snmp_node node; | ||||
|   u16_t subnode_count; | ||||
|   const struct snmp_node* const *subnodes; | ||||
| }; | ||||
| 
 | ||||
| #define SNMP_CREATE_TREE_NODE(oid, subnodes) \ | ||||
|   {{ SNMP_NODE_TREE, (oid) }, \ | ||||
|   (u16_t)LWIP_ARRAYSIZE(subnodes), (subnodes) } | ||||
| 
 | ||||
| #define SNMP_CREATE_EMPTY_TREE_NODE(oid) \ | ||||
|   {{ SNMP_NODE_TREE, (oid) }, \ | ||||
|   0, NULL } | ||||
| 
 | ||||
| /** SNMP leaf node */ | ||||
| struct snmp_leaf_node | ||||
| { | ||||
|   /** inherited "base class" members */ | ||||
|   struct snmp_node node; | ||||
|   snmp_err_t (*get_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
|   snmp_err_t (*get_next_instance)(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| }; | ||||
| 
 | ||||
| /** represents a single mib with its base oid and root node */ | ||||
| struct snmp_mib | ||||
| { | ||||
|   const u32_t *base_oid; | ||||
|   u8_t base_oid_len; | ||||
|   const struct snmp_node *root_node; | ||||
| }; | ||||
| 
 | ||||
| #define SNMP_MIB_CREATE(oid_list, root_node) { (oid_list), (u8_t)LWIP_ARRAYSIZE(oid_list), root_node } | ||||
| 
 | ||||
| /** OID range structure */ | ||||
| struct snmp_oid_range | ||||
| { | ||||
|   u32_t min; | ||||
|   u32_t max; | ||||
| }; | ||||
| 
 | ||||
| /** checks if incoming OID length and values are in allowed ranges */ | ||||
| u8_t snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len); | ||||
| 
 | ||||
| typedef enum { | ||||
|   SNMP_NEXT_OID_STATUS_SUCCESS, | ||||
|   SNMP_NEXT_OID_STATUS_NO_MATCH, | ||||
|   SNMP_NEXT_OID_STATUS_BUF_TO_SMALL | ||||
| } snmp_next_oid_status_t; | ||||
| 
 | ||||
| /** state for next_oid_init / next_oid_check functions */ | ||||
| struct snmp_next_oid_state | ||||
| { | ||||
|   const u32_t* start_oid; | ||||
|   u8_t start_oid_len; | ||||
| 
 | ||||
|   u32_t* next_oid; | ||||
|   u8_t next_oid_len; | ||||
|   u8_t next_oid_max_len; | ||||
| 
 | ||||
|   snmp_next_oid_status_t status; | ||||
|   void* reference; | ||||
| }; | ||||
| 
 | ||||
| void snmp_next_oid_init(struct snmp_next_oid_state *state, | ||||
|   const u32_t *start_oid, u8_t start_oid_len, | ||||
|   u32_t *next_oid_buf, u8_t next_oid_max_len); | ||||
| u8_t snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len); | ||||
| u8_t snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, const u8_t oid_len, void* reference); | ||||
| 
 | ||||
| void snmp_oid_assign(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); | ||||
| void snmp_oid_combine(struct snmp_obj_id* target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); | ||||
| void snmp_oid_prefix(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); | ||||
| void snmp_oid_append(struct snmp_obj_id* target, const u32_t *oid, u8_t oid_len); | ||||
| u8_t snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); | ||||
| s8_t snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len); | ||||
| 
 | ||||
| #if LWIP_IPV4 | ||||
| u8_t snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip); | ||||
| void snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid); | ||||
| #endif /* LWIP_IPV4 */ | ||||
| #if LWIP_IPV6 | ||||
| u8_t snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip); | ||||
| void snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid); | ||||
| #endif /* LWIP_IPV6 */ | ||||
| #if LWIP_IPV4 || LWIP_IPV6 | ||||
| u8_t snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid); | ||||
| u8_t snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid); | ||||
| 
 | ||||
| u8_t snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip); | ||||
| u8_t snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port); | ||||
| #endif /* LWIP_IPV4 || LWIP_IPV6 */ | ||||
| 
 | ||||
| struct netif; | ||||
| u8_t netif_to_num(const struct netif *netif); | ||||
| 
 | ||||
| snmp_err_t snmp_set_test_ok(struct snmp_node_instance* instance, u16_t value_len, void* value); /* generic function which can be used if test is always successful */ | ||||
| 
 | ||||
| err_t snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value); | ||||
| err_t snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value); | ||||
| u8_t  snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count); | ||||
| u8_t  snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value); | ||||
| 
 | ||||
| struct snmp_statistics | ||||
| { | ||||
|   u32_t inpkts; | ||||
|   u32_t outpkts; | ||||
|   u32_t inbadversions; | ||||
|   u32_t inbadcommunitynames; | ||||
|   u32_t inbadcommunityuses; | ||||
|   u32_t inasnparseerrs; | ||||
|   u32_t intoobigs; | ||||
|   u32_t innosuchnames; | ||||
|   u32_t inbadvalues; | ||||
|   u32_t inreadonlys; | ||||
|   u32_t ingenerrs; | ||||
|   u32_t intotalreqvars; | ||||
|   u32_t intotalsetvars; | ||||
|   u32_t ingetrequests; | ||||
|   u32_t ingetnexts; | ||||
|   u32_t insetrequests; | ||||
|   u32_t ingetresponses; | ||||
|   u32_t intraps; | ||||
|   u32_t outtoobigs; | ||||
|   u32_t outnosuchnames; | ||||
|   u32_t outbadvalues; | ||||
|   u32_t outgenerrs; | ||||
|   u32_t outgetrequests; | ||||
|   u32_t outgetnexts; | ||||
|   u32_t outsetrequests; | ||||
|   u32_t outgetresponses; | ||||
|   u32_t outtraps; | ||||
| }; | ||||
| 
 | ||||
| extern struct snmp_statistics snmp_stats; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_CORE_H */ | ||||
|  | @ -0,0 +1,78 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP MIB2 API | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Dirk Ziegelmeier <dziegel@gmx.de> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_SNMP_MIB2_H | ||||
| #define LWIP_HDR_APPS_SNMP_MIB2_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| #if SNMP_LWIP_MIB2 | ||||
| 
 | ||||
| #include "lwip/apps/snmp_core.h" | ||||
| 
 | ||||
| extern const struct snmp_mib mib2; | ||||
| 
 | ||||
| #if SNMP_USE_NETCONN | ||||
| #include "lwip/apps/snmp_threadsync.h" | ||||
| void snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void* arg); | ||||
| extern struct snmp_threadsync_instance snmp_mib2_lwip_locks; | ||||
| #endif | ||||
| 
 | ||||
| #ifndef SNMP_SYSSERVICES | ||||
| #define SNMP_SYSSERVICES ((1 << 6) | (1 << 3) | ((IP_FORWARD) << 2)) | ||||
| #endif | ||||
| 
 | ||||
| void snmp_mib2_set_sysdescr(const u8_t* str, const u16_t* len); /* read-only be defintion */ | ||||
| void snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); | ||||
| void snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen); | ||||
| void snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); | ||||
| void snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen); | ||||
| void snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize); | ||||
| void snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen); | ||||
| 
 | ||||
| #endif /* SNMP_LWIP_MIB2 */ | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_MIB2_H */ | ||||
|  | @ -0,0 +1,293 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP server options list | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (c) 2015 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. | ||||
|  * | ||||
|  * This file is part of the lwIP TCP/IP stack. | ||||
|  * | ||||
|  * Author: Dirk Ziegelmeier | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_SNMP_OPTS_H | ||||
| #define LWIP_HDR_SNMP_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup snmp_opts Options | ||||
|  * @ingroup snmp | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * LWIP_SNMP==1: This enables the lwIP SNMP agent. UDP must be available | ||||
|  * for SNMP transport. | ||||
|  * If you want to use your own SNMP agent, leave this disabled. | ||||
|  * To integrate MIB2 of an external agent, you need to enable | ||||
|  * LWIP_MIB2_CALLBACKS and MIB2_STATS. This will give you the callbacks | ||||
|  * and statistics counters you need to get MIB2 working. | ||||
|  */ | ||||
| #if !defined LWIP_SNMP || defined __DOXYGEN__ | ||||
| #define LWIP_SNMP                       0 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_USE_NETCONN: Use netconn API instead of raw API. | ||||
|  * Makes SNMP agent run in a worker thread, so blocking operations | ||||
|  * can be done in MIB calls. | ||||
|  */ | ||||
| #if !defined SNMP_USE_NETCONN || defined __DOXYGEN__ | ||||
| #define SNMP_USE_NETCONN           0 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_USE_RAW: Use raw API. | ||||
|  * SNMP agent does not run in a worker thread, so blocking operations | ||||
|  * should not be done in MIB calls. | ||||
|  */ | ||||
| #if !defined SNMP_USE_RAW || defined __DOXYGEN__ | ||||
| #define SNMP_USE_RAW               1 | ||||
| #endif | ||||
| 
 | ||||
| #if SNMP_USE_NETCONN && SNMP_USE_RAW | ||||
| #error SNMP stack can use only one of the APIs {raw, netconn} | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP && !SNMP_USE_NETCONN && !SNMP_USE_RAW | ||||
| #error SNMP stack needs a receive API and UDP {raw, netconn} | ||||
| #endif | ||||
| 
 | ||||
| #if SNMP_USE_NETCONN | ||||
| /**
 | ||||
|  * SNMP_STACK_SIZE: Stack size of SNMP netconn worker thread | ||||
|  */ | ||||
| #if !defined SNMP_STACK_SIZE || defined __DOXYGEN__ | ||||
| #define SNMP_STACK_SIZE            DEFAULT_THREAD_STACKSIZE | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_THREAD_PRIO: SNMP netconn worker thread priority | ||||
|  */ | ||||
| #if !defined SNMP_THREAD_PRIO || defined __DOXYGEN__ | ||||
| #define SNMP_THREAD_PRIO           DEFAULT_THREAD_PRIO | ||||
| #endif | ||||
| #endif /* SNMP_USE_NETCONN */ | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap | ||||
|  * destination is required | ||||
|  */ | ||||
| #if !defined SNMP_TRAP_DESTINATIONS || defined __DOXYGEN__ | ||||
| #define SNMP_TRAP_DESTINATIONS          1 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not | ||||
|  * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). | ||||
|  * Unsafe requests are disabled by default! | ||||
|  */ | ||||
| #if !defined SNMP_SAFE_REQUESTS || defined __DOXYGEN__ | ||||
| #define SNMP_SAFE_REQUESTS              1 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The maximum length of strings used. | ||||
|  */ | ||||
| #if !defined SNMP_MAX_OCTET_STRING_LEN || defined __DOXYGEN__ | ||||
| #define SNMP_MAX_OCTET_STRING_LEN       127 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The maximum number of Sub ID's inside an object identifier. | ||||
|  * Indirectly this also limits the maximum depth of SNMP tree. | ||||
|  */ | ||||
| #if !defined SNMP_MAX_OBJ_ID_LEN || defined __DOXYGEN__ | ||||
| #define SNMP_MAX_OBJ_ID_LEN             50 | ||||
| #endif | ||||
| 
 | ||||
| #if !defined SNMP_MAX_VALUE_SIZE || defined __DOXYGEN__ | ||||
| /**
 | ||||
|  * The maximum size of a value. | ||||
|  */ | ||||
| #define SNMP_MIN_VALUE_SIZE             (2 * sizeof(u32_t*)) /* size required to store the basic types (8 bytes for counter64) */ | ||||
| /**
 | ||||
|  * The minimum size of a value. | ||||
|  */ | ||||
| #define SNMP_MAX_VALUE_SIZE             LWIP_MAX(LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN), sizeof(u32_t)*(SNMP_MAX_OBJ_ID_LEN)), SNMP_MIN_VALUE_SIZE) | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The snmp read-access community. Used for write-access and traps, too | ||||
|  * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. | ||||
|  */ | ||||
| #if !defined SNMP_COMMUNITY || defined __DOXYGEN__ | ||||
| #define SNMP_COMMUNITY                  "public" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The snmp write-access community. | ||||
|  * Set this community to "" in order to disallow any write access. | ||||
|  */ | ||||
| #if !defined SNMP_COMMUNITY_WRITE || defined __DOXYGEN__ | ||||
| #define SNMP_COMMUNITY_WRITE            "private" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The snmp community used for sending traps. | ||||
|  */ | ||||
| #if !defined SNMP_COMMUNITY_TRAP || defined __DOXYGEN__ | ||||
| #define SNMP_COMMUNITY_TRAP             "public" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The maximum length of community string. | ||||
|  * If community names shall be adjusted at runtime via snmp_set_community() calls, | ||||
|  * enter here the possible maximum length (+1 for terminating null character). | ||||
|  */ | ||||
| #if !defined SNMP_MAX_COMMUNITY_STR_LEN || defined __DOXYGEN__ | ||||
| #define SNMP_MAX_COMMUNITY_STR_LEN LWIP_MAX(LWIP_MAX(sizeof(SNMP_COMMUNITY), sizeof(SNMP_COMMUNITY_WRITE)), sizeof(SNMP_COMMUNITY_TRAP)) | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * The OID identifiying the device. This may be the enterprise OID itself or any OID located below it in tree. | ||||
|  */ | ||||
| #if !defined SNMP_DEVICE_ENTERPRISE_OID || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_ENTERPRISE_OID 26381 | ||||
| /**
 | ||||
|  * IANA assigned enterprise ID for lwIP is 26381 | ||||
|  * @see http://www.iana.org/assignments/enterprise-numbers
 | ||||
|  * | ||||
|  * @note this enterprise ID is assigned to the lwIP project, | ||||
|  * all object identifiers living under this ID are assigned | ||||
|  * by the lwIP maintainers! | ||||
|  * @note don't change this define, use snmp_set_device_enterprise_oid() | ||||
|  * | ||||
|  * If you need to create your own private MIB you'll need | ||||
|  * to apply for your own enterprise ID with IANA: | ||||
|  * http://www.iana.org/numbers.html
 | ||||
|  */ | ||||
| #define SNMP_DEVICE_ENTERPRISE_OID {1, 3, 6, 1, 4, 1, SNMP_LWIP_ENTERPRISE_OID} | ||||
| /**
 | ||||
|  * Length of SNMP_DEVICE_ENTERPRISE_OID | ||||
|  */ | ||||
| #define SNMP_DEVICE_ENTERPRISE_OID_LEN 7 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_DEBUG: Enable debugging for SNMP messages. | ||||
|  */ | ||||
| #if !defined SNMP_DEBUG || defined __DOXYGEN__ | ||||
| #define SNMP_DEBUG                      LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. | ||||
|  */ | ||||
| #if !defined SNMP_MIB_DEBUG || defined __DOXYGEN__ | ||||
| #define SNMP_MIB_DEBUG                  LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Indicates if the MIB2 implementation of LWIP SNMP stack is used. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_MIB2 || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_MIB2                      LWIP_SNMP | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Value return for sysDesc field of MIB2. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_MIB2_SYSDESC || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_MIB2_SYSDESC              "lwIP" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Value return for sysName field of MIB2. | ||||
|  * To make sysName field settable, call snmp_mib2_set_sysname() to provide the necessary buffers. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_MIB2_SYSNAME || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_MIB2_SYSNAME              "FQDN-unk" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Value return for sysContact field of MIB2. | ||||
|  * To make sysContact field settable, call snmp_mib2_set_syscontact() to provide the necessary buffers. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_MIB2_SYSCONTACT || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_MIB2_SYSCONTACT           "" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Value return for sysLocation field of MIB2. | ||||
|  * To make sysLocation field settable, call snmp_mib2_set_syslocation() to provide the necessary buffers. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_MIB2_SYSLOCATION || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_MIB2_SYSLOCATION          "" | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * This value is used to limit the repetitions processed in GetBulk requests (value == 0 means no limitation). | ||||
|  * This may be useful to limit the load for a single request. | ||||
|  * According to SNMP RFC 1905 it is allowed to not return all requested variables from a GetBulk request if system load would be too high. | ||||
|  * so the effect is that the client will do more requests to gather all data. | ||||
|  * For the stack this could be useful in case that SNMP processing is done in TCP/IP thread. In this situation a request with many | ||||
|  * repetitions could block the thread for a longer time. Setting limit here will keep the stack more responsive. | ||||
|  */ | ||||
| #if !defined SNMP_LWIP_GETBULK_MAX_REPETITIONS || defined __DOXYGEN__ | ||||
| #define SNMP_LWIP_GETBULK_MAX_REPETITIONS 0 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|    ------------------------------------ | ||||
|    ---------- SNMPv3 options ---------- | ||||
|    ------------------------------------ | ||||
| */ | ||||
| 
 | ||||
| /**
 | ||||
|  * LWIP_SNMP_V3==1: This enables EXPERIMENTAL SNMPv3 support. LWIP_SNMP must | ||||
|  * also be enabled. | ||||
|  * THIS IS UNDER DEVELOPMENT AND SHOULD NOT BE ENABLED IN PRODUCTS. | ||||
|  */ | ||||
| #ifndef LWIP_SNMP_V3 | ||||
| #define LWIP_SNMP_V3               0 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef LWIP_SNMP_V3_CRYPTO | ||||
| #define LWIP_SNMP_V3_CRYPTO        LWIP_SNMP_V3 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef LWIP_SNMP_V3_MBEDTLS | ||||
| #define LWIP_SNMP_V3_MBEDTLS       LWIP_SNMP_V3 | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_SNMP_OPTS_H */ | ||||
|  | @ -0,0 +1,113 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP server MIB API to implement scalar nodes | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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_SCALAR_H | ||||
| #define LWIP_HDR_APPS_SNMP_SCALAR_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| #include "lwip/apps/snmp_core.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| 
 | ||||
| /** basic scalar node */ | ||||
| struct snmp_scalar_node | ||||
| { | ||||
|   /** inherited "base class" members */ | ||||
|   struct snmp_leaf_node node; | ||||
|   u8_t asn1_type; | ||||
|   snmp_access_t access; | ||||
|   node_instance_get_value_method get_value; | ||||
|   node_instance_set_test_method set_test; | ||||
|   node_instance_set_value_method set_value; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| snmp_err_t snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| snmp_err_t snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| 
 | ||||
| #define SNMP_SCALAR_CREATE_NODE(oid, access, asn1_type, get_value_method, set_test_method, set_value_method) \ | ||||
|   {{{ SNMP_NODE_SCALAR, (oid) }, \ | ||||
|     snmp_scalar_get_instance, \ | ||||
|     snmp_scalar_get_next_instance }, \ | ||||
|     (asn1_type), (access), (get_value_method), (set_test_method), (set_value_method) } | ||||
| 
 | ||||
| #define SNMP_SCALAR_CREATE_NODE_READONLY(oid, asn1_type, get_value_method) SNMP_SCALAR_CREATE_NODE(oid, SNMP_NODE_INSTANCE_READ_ONLY, asn1_type, get_value_method, NULL, NULL) | ||||
| 
 | ||||
| /** scalar array node - a tree node which contains scalars only as children */ | ||||
| struct snmp_scalar_array_node_def | ||||
| { | ||||
|   u32_t         oid; | ||||
|   u8_t          asn1_type; | ||||
|   snmp_access_t access; | ||||
| }; | ||||
| 
 | ||||
| typedef s16_t (*snmp_scalar_array_get_value_method)(const struct snmp_scalar_array_node_def*, void*); | ||||
| typedef snmp_err_t (*snmp_scalar_array_set_test_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); | ||||
| typedef snmp_err_t (*snmp_scalar_array_set_value_method)(const struct snmp_scalar_array_node_def*, u16_t, void*); | ||||
| 
 | ||||
| /** basic scalar array node */ | ||||
| struct snmp_scalar_array_node | ||||
| { | ||||
|   /** inherited "base class" members */ | ||||
|   struct snmp_leaf_node node; | ||||
|   u16_t array_node_count; | ||||
|   const struct snmp_scalar_array_node_def* array_nodes; | ||||
|   snmp_scalar_array_get_value_method get_value; | ||||
|   snmp_scalar_array_set_test_method set_test; | ||||
|   snmp_scalar_array_set_value_method set_value; | ||||
| }; | ||||
| 
 | ||||
| snmp_err_t snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| snmp_err_t snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| 
 | ||||
| #define SNMP_SCALAR_CREATE_ARRAY_NODE(oid, array_nodes, get_value_method, set_test_method, set_value_method) \ | ||||
|   {{{ SNMP_NODE_SCALAR_ARRAY, (oid) }, \ | ||||
|     snmp_scalar_array_get_instance, \ | ||||
|     snmp_scalar_array_get_next_instance }, \ | ||||
|     (u16_t)LWIP_ARRAYSIZE(array_nodes), (array_nodes), (get_value_method), (set_test_method), (set_value_method) } | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_SCALAR_H */ | ||||
|  | @ -0,0 +1,134 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP server MIB API to implement table nodes | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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_TABLE_H | ||||
| #define LWIP_HDR_APPS_SNMP_TABLE_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| #include "lwip/apps/snmp_core.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| 
 | ||||
| /** default (customizable) read/write table */ | ||||
| struct snmp_table_col_def | ||||
| { | ||||
|   u32_t index; | ||||
|   u8_t asn1_type; | ||||
|   snmp_access_t access; | ||||
| }; | ||||
| 
 | ||||
| /** table node */ | ||||
| struct snmp_table_node | ||||
| { | ||||
|   /** inherited "base class" members */ | ||||
|   struct snmp_leaf_node node; | ||||
|   u16_t column_count; | ||||
|   const struct snmp_table_col_def* columns; | ||||
|   snmp_err_t (*get_cell_instance)(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, struct snmp_node_instance* cell_instance); | ||||
|   snmp_err_t (*get_next_cell_instance)(const u32_t* column, struct snmp_obj_id* row_oid, struct snmp_node_instance* cell_instance); | ||||
|   /** returns object value for the given object identifier */ | ||||
|   node_instance_get_value_method get_value; | ||||
|   /** tests length and/or range BEFORE setting */ | ||||
|   node_instance_set_test_method set_test; | ||||
|   /** sets object value, only called when set_test() was successful */ | ||||
|   node_instance_set_value_method set_value; | ||||
| }; | ||||
| 
 | ||||
| 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 snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| 
 | ||||
| #define SNMP_TABLE_CREATE(oid, columns, get_cell_instance_method, get_next_cell_instance_method, get_value_method, set_test_method, set_value_method) \ | ||||
|   {{{ SNMP_NODE_TABLE, (oid) }, \ | ||||
|   snmp_table_get_instance, \ | ||||
|   snmp_table_get_next_instance }, \ | ||||
|   (u16_t)LWIP_ARRAYSIZE(columns), (columns), \ | ||||
|   (get_cell_instance_method), (get_next_cell_instance_method), \ | ||||
|   (get_value_method), (set_test_method), (set_value_method)} | ||||
| 
 | ||||
| #define SNMP_TABLE_GET_COLUMN_FROM_OID(oid) ((oid)[1]) /* first array value is (fixed) row entry (fixed to 1) and 2nd value is column, follow3ed by instance */ | ||||
| 
 | ||||
| 
 | ||||
| /** simple read-only table */ | ||||
| typedef enum { | ||||
|   SNMP_VARIANT_VALUE_TYPE_U32, | ||||
|   SNMP_VARIANT_VALUE_TYPE_S32, | ||||
|   SNMP_VARIANT_VALUE_TYPE_PTR, | ||||
|   SNMP_VARIANT_VALUE_TYPE_CONST_PTR | ||||
| } snmp_table_column_data_type_t; | ||||
| 
 | ||||
| struct snmp_table_simple_col_def | ||||
| { | ||||
|   u32_t index; | ||||
|   u8_t asn1_type; | ||||
|   snmp_table_column_data_type_t data_type; /* depending of what union member is used to store the value*/ | ||||
| }; | ||||
| 
 | ||||
| /** simple read-only table node */ | ||||
| struct snmp_table_simple_node | ||||
| { | ||||
|   /* inherited "base class" members */ | ||||
|   struct snmp_leaf_node node; | ||||
|   u16_t column_count; | ||||
|   const struct snmp_table_simple_col_def* columns; | ||||
|   snmp_err_t (*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); | ||||
|   snmp_err_t (*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); | ||||
| }; | ||||
| 
 | ||||
| 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 snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| 
 | ||||
| #define SNMP_TABLE_CREATE_SIMPLE(oid, columns, get_cell_value_method, get_next_cell_instance_and_value_method) \ | ||||
|   {{{ SNMP_NODE_TABLE, (oid) }, \ | ||||
|   snmp_table_simple_get_instance, \ | ||||
|   snmp_table_simple_get_next_instance }, \ | ||||
|   (u16_t)LWIP_ARRAYSIZE(columns), (columns), (get_cell_value_method), (get_next_cell_instance_and_value_method) } | ||||
| 
 | ||||
| s16_t snmp_table_extract_value_from_s32ref(struct snmp_node_instance* instance, void* value); | ||||
| s16_t snmp_table_extract_value_from_u32ref(struct snmp_node_instance* instance, void* value); | ||||
| s16_t snmp_table_extract_value_from_refconstptr(struct snmp_node_instance* instance, void* value); | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_TABLE_H */ | ||||
|  | @ -0,0 +1,114 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNMP server MIB API to implement thread synchronization | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Dirk Ziegelmeier <dziegel@gmx.de> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_SNMP_THREADSYNC_H | ||||
| #define LWIP_HDR_APPS_SNMP_THREADSYNC_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ | ||||
| 
 | ||||
| #include "lwip/apps/snmp_core.h" | ||||
| #include "lwip/sys.h" | ||||
| 
 | ||||
| typedef void (*snmp_threadsync_called_fn)(void* arg); | ||||
| typedef void (*snmp_threadsync_synchronizer_fn)(snmp_threadsync_called_fn fn, void* arg); | ||||
| 
 | ||||
| 
 | ||||
| /** Thread sync runtime data. For internal usage only. */ | ||||
| struct threadsync_data | ||||
| { | ||||
|   union { | ||||
|     snmp_err_t err; | ||||
|     s16_t s16; | ||||
|   } retval; | ||||
|   union { | ||||
|     const u32_t *root_oid; | ||||
|     void *value; | ||||
|   } arg1; | ||||
|   union { | ||||
|     u8_t root_oid_len; | ||||
|     u16_t len; | ||||
|   } arg2; | ||||
|   const struct snmp_threadsync_node *threadsync_node; | ||||
|   struct snmp_node_instance proxy_instance; | ||||
| }; | ||||
| 
 | ||||
| /** Thread sync instance. Needed EXCATLY once for every thread to be synced into. */ | ||||
| struct snmp_threadsync_instance | ||||
| { | ||||
|   sys_sem_t                       sem; | ||||
|   sys_mutex_t                     sem_usage_mutex; | ||||
|   snmp_threadsync_synchronizer_fn sync_fn; | ||||
|   struct threadsync_data          data; | ||||
| }; | ||||
| 
 | ||||
| /** SNMP thread sync proxy leaf node */ | ||||
| struct snmp_threadsync_node | ||||
| { | ||||
|   /* inherited "base class" members */ | ||||
|   struct snmp_leaf_node           node; | ||||
| 
 | ||||
|   const struct snmp_leaf_node     *target; | ||||
|   struct snmp_threadsync_instance *instance; | ||||
| }; | ||||
| 
 | ||||
| snmp_err_t snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| snmp_err_t snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance); | ||||
| 
 | ||||
| /** Create thread sync proxy node */ | ||||
| #define SNMP_CREATE_THREAD_SYNC_NODE(oid, target_leaf_node, threadsync_instance) \ | ||||
|   {{{ SNMP_NODE_THREADSYNC, (oid) }, \ | ||||
|     snmp_threadsync_get_instance, \ | ||||
|     snmp_threadsync_get_next_instance }, \ | ||||
|     (target_leaf_node), \ | ||||
|     (threadsync_instance) } | ||||
| 
 | ||||
| /** Create thread sync instance data */ | ||||
| void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn); | ||||
| 
 | ||||
| #endif /* LWIP_SNMP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_THREADSYNC_H */ | ||||
|  | @ -0,0 +1,90 @@ | |||
| /**
 | ||||
|  * @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> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_SNMP_V3_H | ||||
| #define LWIP_HDR_APPS_SNMP_V3_H | ||||
| 
 | ||||
| #include "lwip/apps/snmp_opts.h" | ||||
| #include "lwip/err.h" | ||||
| 
 | ||||
| #if LWIP_SNMP && LWIP_SNMP_V3 | ||||
| 
 | ||||
| #define SNMP_V3_AUTH_ALGO_INVAL  0 | ||||
| #define SNMP_V3_AUTH_ALGO_MD5    1 | ||||
| #define SNMP_V3_AUTH_ALGO_SHA    2 | ||||
| 
 | ||||
| #define SNMP_V3_PRIV_ALGO_INVAL  0 | ||||
| #define SNMP_V3_PRIV_ALGO_DES    1 | ||||
| #define SNMP_V3_PRIV_ALGO_AES    2 | ||||
| 
 | ||||
| #define SNMP_V3_PRIV_MODE_DECRYPT  0 | ||||
| #define SNMP_V3_PRIV_MODE_ENCRYPT  1 | ||||
| 
 | ||||
| /*
 | ||||
|  * The following callback functions must be implemented by the application. | ||||
|  * There is a dummy implementation in snmpv3_dummy.c. | ||||
|  */ | ||||
| 
 | ||||
| void snmpv3_get_engine_id(const char **id, u8_t *len); | ||||
| err_t snmpv3_set_engine_id(const char* id, u8_t len); | ||||
| 
 | ||||
| u32_t snmpv3_get_engine_boots(void); | ||||
| void snmpv3_set_engine_boots(u32_t boots); | ||||
| 
 | ||||
| u32_t snmpv3_get_engine_time(void); | ||||
| void snmpv3_reset_engine_time(void); | ||||
| 
 | ||||
| err_t snmpv3_get_user(const char* username, u8_t *auth_algo, u8_t *auth_key, u8_t *priv_algo, u8_t *priv_key); | ||||
| 
 | ||||
| /* The following functions are provided by the SNMPv3 agent */ | ||||
| 
 | ||||
| void snmpv3_engine_id_changed(void); | ||||
| 
 | ||||
| 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 */ | ||||
| 
 | ||||
| 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 */ | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNMP_V3_H */ | ||||
|  | @ -0,0 +1,76 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNTP client API | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_SNTP_H | ||||
| #define LWIP_HDR_APPS_SNTP_H | ||||
| 
 | ||||
| #include "lwip/apps/sntp_opts.h" | ||||
| #include "lwip/ip_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* SNTP operating modes: default is to poll using unicast.
 | ||||
|    The mode has to be set before calling sntp_init(). */ | ||||
| #define SNTP_OPMODE_POLL            0 | ||||
| #define SNTP_OPMODE_LISTENONLY      1 | ||||
| void sntp_setoperatingmode(u8_t operating_mode); | ||||
| u8_t sntp_getoperatingmode(void); | ||||
| 
 | ||||
| void sntp_init(void); | ||||
| void sntp_stop(void); | ||||
| u8_t sntp_enabled(void); | ||||
| 
 | ||||
| void sntp_setserver(u8_t idx, const ip_addr_t *addr); | ||||
| const ip_addr_t* sntp_getserver(u8_t idx); | ||||
| 
 | ||||
| #if SNTP_SERVER_DNS | ||||
| void sntp_setservername(u8_t idx, char *server); | ||||
| char *sntp_getservername(u8_t idx); | ||||
| #endif /* SNTP_SERVER_DNS */ | ||||
| 
 | ||||
| #if SNTP_GET_SERVERS_FROM_DHCP | ||||
| void sntp_servermode_dhcp(int set_servers_from_dhcp); | ||||
| #else /* SNTP_GET_SERVERS_FROM_DHCP */ | ||||
| #define sntp_servermode_dhcp(x) | ||||
| #endif /* SNTP_GET_SERVERS_FROM_DHCP */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNTP_H */ | ||||
|  | @ -0,0 +1,173 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * SNTP client options list | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_APPS_SNTP_OPTS_H | ||||
| #define LWIP_HDR_APPS_SNTP_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup sntp_opts Options | ||||
|  * @ingroup sntp | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /** SNTP macro to change system time in seconds
 | ||||
|  * Define SNTP_SET_SYSTEM_TIME_US(sec, us) to set the time in microseconds instead of this one | ||||
|  * if you need the additional precision. | ||||
|  */ | ||||
| #if !defined SNTP_SET_SYSTEM_TIME || defined __DOXYGEN__ | ||||
| #define SNTP_SET_SYSTEM_TIME(sec)   LWIP_UNUSED_ARG(sec) | ||||
| #endif | ||||
| 
 | ||||
| /** The maximum number of SNTP servers that can be set */ | ||||
| #if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__ | ||||
| #define SNTP_MAX_SERVERS           LWIP_DHCP_MAX_NTP_SERVERS | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to implement the callback function called by dhcp when
 | ||||
|  * NTP servers are received. */ | ||||
| #if !defined SNTP_GET_SERVERS_FROM_DHCP || defined __DOXYGEN__ | ||||
| #define SNTP_GET_SERVERS_FROM_DHCP LWIP_DHCP_GET_NTP_SRV | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to support DNS names (or IP address strings) to set sntp servers
 | ||||
|  * One server address/name can be defined as default if SNTP_SERVER_DNS == 1: | ||||
|  * \#define SNTP_SERVER_ADDRESS "pool.ntp.org" | ||||
|  */ | ||||
| #if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ | ||||
| #define SNTP_SERVER_DNS            0 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * SNTP_DEBUG: Enable debugging for SNTP. | ||||
|  */ | ||||
| #if !defined SNTP_DEBUG || defined __DOXYGEN__ | ||||
| #define SNTP_DEBUG                  LWIP_DBG_OFF | ||||
| #endif | ||||
| 
 | ||||
| /** SNTP server port */ | ||||
| #if !defined SNTP_PORT || defined __DOXYGEN__ | ||||
| #define SNTP_PORT                   123 | ||||
| #endif | ||||
| 
 | ||||
| /** Set this to 1 to allow config of SNTP server(s) by DNS name */ | ||||
| #if !defined SNTP_SERVER_DNS || defined __DOXYGEN__ | ||||
| #define SNTP_SERVER_DNS             0 | ||||
| #endif | ||||
| 
 | ||||
| /** Sanity check:
 | ||||
|  * Define this to | ||||
|  * - 0 to turn off sanity checks (default; smaller code) | ||||
|  * - >= 1 to check address and port of the response packet to ensure the | ||||
|  *        response comes from the server we sent the request to. | ||||
|  * - >= 2 to check returned Originate Timestamp against Transmit Timestamp | ||||
|  *        sent to the server (to ensure response to older request). | ||||
|  * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp | ||||
|  *        fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). | ||||
|  * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each | ||||
|  *        greater than or equal to 0 and less than infinity, where infinity is | ||||
|  *        currently a cozy number like one second. This check avoids using a | ||||
|  *        server whose synchronization source has expired for a very long time. | ||||
|  */ | ||||
| #if !defined SNTP_CHECK_RESPONSE || defined __DOXYGEN__ | ||||
| #define SNTP_CHECK_RESPONSE         0 | ||||
| #endif | ||||
| 
 | ||||
| /** According to the RFC, this shall be a random delay
 | ||||
|  * between 1 and 5 minutes (in milliseconds) to prevent load peaks. | ||||
|  * This can be defined to a random generation function, | ||||
|  * which must return the delay in milliseconds as u32_t. | ||||
|  * Turned off by default. | ||||
|  */ | ||||
| #if !defined SNTP_STARTUP_DELAY || defined __DOXYGEN__ | ||||
| #define SNTP_STARTUP_DELAY          0 | ||||
| #endif | ||||
| 
 | ||||
| /** If you want the startup delay to be a function, define this
 | ||||
|  * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. | ||||
|  */ | ||||
| #if !defined SNTP_STARTUP_DELAY_FUNC || defined __DOXYGEN__ | ||||
| #define SNTP_STARTUP_DELAY_FUNC     SNTP_STARTUP_DELAY | ||||
| #endif | ||||
| 
 | ||||
| /** SNTP receive timeout - in milliseconds
 | ||||
|  * Also used as retry timeout - this shouldn't be too low. | ||||
|  * Default is 3 seconds. | ||||
|  */ | ||||
| #if !defined SNTP_RECV_TIMEOUT || defined __DOXYGEN__ | ||||
| #define SNTP_RECV_TIMEOUT           3000 | ||||
| #endif | ||||
| 
 | ||||
| /** SNTP update delay - in milliseconds
 | ||||
|  * Default is 1 hour. Must not be beolw 15 seconds by specification (i.e. 15000) | ||||
|  */ | ||||
| #if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__ | ||||
| #define SNTP_UPDATE_DELAY           3600000 | ||||
| #endif | ||||
| 
 | ||||
| /** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
 | ||||
|  * to send in request and compare in response. | ||||
|  */ | ||||
| #if !defined SNTP_GET_SYSTEM_TIME || defined __DOXYGEN__ | ||||
| #define SNTP_GET_SYSTEM_TIME(sec, us)     do { (sec) = 0; (us) = 0; } while(0) | ||||
| #endif | ||||
| 
 | ||||
| /** Default retry timeout (in milliseconds) if the response
 | ||||
|  * received is invalid. | ||||
|  * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. | ||||
|  */ | ||||
| #if !defined SNTP_RETRY_TIMEOUT || defined __DOXYGEN__ | ||||
| #define SNTP_RETRY_TIMEOUT          SNTP_RECV_TIMEOUT | ||||
| #endif | ||||
| 
 | ||||
| /** Maximum retry timeout (in milliseconds). */ | ||||
| #if !defined SNTP_RETRY_TIMEOUT_MAX || defined __DOXYGEN__ | ||||
| #define SNTP_RETRY_TIMEOUT_MAX      (SNTP_RETRY_TIMEOUT * 10) | ||||
| #endif | ||||
| 
 | ||||
| /** Increase retry timeout with every retry sent
 | ||||
|  * Default is on to conform to RFC. | ||||
|  */ | ||||
| #if !defined SNTP_RETRY_TIMEOUT_EXP || defined __DOXYGEN__ | ||||
| #define SNTP_RETRY_TIMEOUT_EXP      1 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_SNTP_OPTS_H */ | ||||
|  | @ -0,0 +1,105 @@ | |||
| /****************************************************************//**
 | ||||
|  * | ||||
|  * @file tftp_opts.h | ||||
|  * | ||||
|  * @author   Logan Gunthorpe <logang@deltatee.com> | ||||
|  * | ||||
|  * @brief    Trivial File Transfer Protocol (RFC 1350) implementation options | ||||
|  * | ||||
|  * Copyright (c) Deltatee Enterprises Ltd. 2013 | ||||
|  * 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: Logan Gunthorpe <logang@deltatee.com> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_TFTP_OPTS_H | ||||
| #define LWIP_HDR_APPS_TFTP_OPTS_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * @defgroup tftp_opts Options | ||||
|  * @ingroup tftp | ||||
|  * @{ | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Enable TFTP debug messages | ||||
|  */ | ||||
| #if !defined TFTP_DEBUG || defined __DOXYGEN__ | ||||
| #define TFTP_DEBUG            LWIP_DBG_ON | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * TFTP server port | ||||
|  */ | ||||
| #if !defined TFTP_PORT || defined __DOXYGEN__ | ||||
| #define TFTP_PORT             69 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * TFTP timeout | ||||
|  */ | ||||
| #if !defined TFTP_TIMEOUT_MSECS || defined __DOXYGEN__ | ||||
| #define TFTP_TIMEOUT_MSECS    10000 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Max. number of retries when a file is read from server | ||||
|  */ | ||||
| #if !defined TFTP_MAX_RETRIES || defined __DOXYGEN__ | ||||
| #define TFTP_MAX_RETRIES      5 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * TFTP timer cyclic interval | ||||
|  */ | ||||
| #if !defined TFTP_TIMER_MSECS || defined __DOXYGEN__ | ||||
| #define TFTP_TIMER_MSECS      50 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Max. length of TFTP filename | ||||
|  */ | ||||
| #if !defined TFTP_MAX_FILENAME_LEN || defined __DOXYGEN__ | ||||
| #define TFTP_MAX_FILENAME_LEN 20 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Max. length of TFTP mode | ||||
|  */ | ||||
| #if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ | ||||
| #define TFTP_MAX_MODE_LEN     7 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @} | ||||
|  */ | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_TFTP_OPTS_H */ | ||||
|  | @ -0,0 +1,94 @@ | |||
| /****************************************************************//**
 | ||||
|  * | ||||
|  * @file tftp_server.h | ||||
|  * | ||||
|  * @author   Logan Gunthorpe <logang@deltatee.com> | ||||
|  * | ||||
|  * @brief    Trivial File Transfer Protocol (RFC 1350) | ||||
|  * | ||||
|  * Copyright (c) Deltatee Enterprises Ltd. 2013 | ||||
|  * 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: Logan Gunthorpe <logang@deltatee.com> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_APPS_TFTP_SERVER_H | ||||
| #define LWIP_HDR_APPS_TFTP_SERVER_H | ||||
| 
 | ||||
| #include "lwip/apps/tftp_opts.h" | ||||
| #include "lwip/err.h" | ||||
| #include "lwip/pbuf.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** @ingroup tftp
 | ||||
|  * TFTP context containing callback functions for TFTP transfers | ||||
|  */ | ||||
| struct tftp_context { | ||||
|   /**
 | ||||
|    * Open file for read/write. | ||||
|    * @param fname Filename | ||||
|    * @param mode Mode string from TFTP RFC 1350 (netascii, octet, mail) | ||||
|    * @param write Flag indicating read (0) or write (!= 0) access | ||||
|    * @returns File handle supplied to other functions | ||||
|    */ | ||||
|   void* (*open)(const char* fname, const char* mode, u8_t write); | ||||
|   /**
 | ||||
|    * Close file handle | ||||
|    * @param handle File handle returned by open() | ||||
|    */ | ||||
|   void (*close)(void* handle); | ||||
|   /**
 | ||||
|    * Read from file  | ||||
|    * @param handle File handle returned by open() | ||||
|    * @param buf Target buffer to copy read data to | ||||
|    * @param bytes Number of bytes to copy to buf | ||||
|    * @returns >= 0: Success; < 0: Error | ||||
|    */ | ||||
|   int (*read)(void* handle, void* buf, int bytes); | ||||
|   /**
 | ||||
|    * Write to file | ||||
|    * @param handle File handle returned by open() | ||||
|    * @param pbuf PBUF adjusted such that payload pointer points | ||||
|    *             to the beginning of write data. In other words, | ||||
|    *             TFTP headers are stripped off. | ||||
|    * @returns >= 0: Success; < 0: Error | ||||
|    */ | ||||
|   int (*write)(void* handle, struct pbuf* p); | ||||
| }; | ||||
| 
 | ||||
| err_t tftp_init(const struct tftp_context* ctx); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_APPS_TFTP_SERVER_H */ | ||||
|  | @ -70,6 +70,45 @@ extern "C" { | |||
| #define DNS_RRCLASS_HS            4     /* Hesiod [Dyer 87] */ | ||||
| #define DNS_RRCLASS_FLUSH         0x800 /* Flush bit */ | ||||
| 
 | ||||
| /* DNS protocol flags */ | ||||
| #define DNS_FLAG1_RESPONSE        0x80 | ||||
| #define DNS_FLAG1_OPCODE_STATUS   0x10 | ||||
| #define DNS_FLAG1_OPCODE_INVERSE  0x08 | ||||
| #define DNS_FLAG1_OPCODE_STANDARD 0x00 | ||||
| #define DNS_FLAG1_AUTHORATIVE     0x04 | ||||
| #define DNS_FLAG1_TRUNC           0x02 | ||||
| #define DNS_FLAG1_RD              0x01 | ||||
| #define DNS_FLAG2_RA              0x80 | ||||
| #define DNS_FLAG2_ERR_MASK        0x0f | ||||
| #define DNS_FLAG2_ERR_NONE        0x00 | ||||
| #define DNS_FLAG2_ERR_NAME        0x03 | ||||
| 
 | ||||
| /* DNS protocol states */ | ||||
| #define DNS_STATE_UNUSED          0 | ||||
| #define DNS_STATE_NEW             1 | ||||
| #define DNS_STATE_ASKING          2 | ||||
| #define DNS_STATE_DONE            3 | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** DNS message header */ | ||||
| struct dns_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t id); | ||||
|   PACK_STRUCT_FIELD(u8_t flags1); | ||||
|   PACK_STRUCT_FIELD(u8_t flags2); | ||||
|   PACK_STRUCT_FIELD(u16_t numquestions); | ||||
|   PACK_STRUCT_FIELD(u16_t numanswers); | ||||
|   PACK_STRUCT_FIELD(u16_t numauthrr); | ||||
|   PACK_STRUCT_FIELD(u16_t numextrarr); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| #define SIZEOF_DNS_HDR 12 | ||||
| 
 | ||||
| /* The size used for the next line is rather a hack, but it prevents including socket.h in all files
 | ||||
|    that include memp.h, and that would possibly break portability (since socket.h defines some types | ||||
|    and constants possibly already define by the OS). | ||||
|  |  | |||
|  | @ -0,0 +1,78 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * AutoIP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * | ||||
|  * Copyright (c) 2007 Dominik Spies <kontakt@dspies.de> | ||||
|  * 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: Dominik Spies <kontakt@dspies.de> | ||||
|  * | ||||
|  * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform | ||||
|  * with RFC 3927. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_PROT_AUTOIP_H | ||||
| #define LWIP_HDR_PROT_AUTOIP_H | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* 169.254.0.0 */ | ||||
| #define AUTOIP_NET              0xA9FE0000 | ||||
| /* 169.254.1.0 */ | ||||
| #define AUTOIP_RANGE_START      (AUTOIP_NET | 0x0100) | ||||
| /* 169.254.254.255 */ | ||||
| #define AUTOIP_RANGE_END        (AUTOIP_NET | 0xFEFF) | ||||
| 
 | ||||
| /* RFC 3927 Constants */ | ||||
| #define PROBE_WAIT              1   /* second   (initial random delay)                 */ | ||||
| #define PROBE_MIN               1   /* second   (minimum delay till repeated probe)    */ | ||||
| #define PROBE_MAX               2   /* seconds  (maximum delay till repeated probe)    */ | ||||
| #define PROBE_NUM               3   /*          (number of probe packets)              */ | ||||
| #define ANNOUNCE_NUM            2   /*          (number of announcement packets)       */ | ||||
| #define ANNOUNCE_INTERVAL       2   /* seconds  (time between announcement packets)    */ | ||||
| #define ANNOUNCE_WAIT           2   /* seconds  (delay before announcing)              */ | ||||
| #define MAX_CONFLICTS           10  /*          (max conflicts before rate limiting)   */ | ||||
| #define RATE_LIMIT_INTERVAL     60  /* seconds  (delay between successive attempts)    */ | ||||
| #define DEFEND_INTERVAL         10  /* seconds  (min. wait between defensive ARPs)     */ | ||||
| 
 | ||||
| /* AutoIP client states */ | ||||
| typedef enum { | ||||
|   AUTOIP_STATE_OFF        = 0, | ||||
|   AUTOIP_STATE_PROBING    = 1, | ||||
|   AUTOIP_STATE_ANNOUNCING = 2, | ||||
|   AUTOIP_STATE_BOUND      = 3 | ||||
| } autoip_state_enum_t; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_AUTOIP_H */ | ||||
|  | @ -0,0 +1,183 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * DHCP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (c) 2001-2004 Leon Woestenberg <leon.woestenberg@gmx.net> | ||||
|  * Copyright (c) 2001-2004 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. | ||||
|  * | ||||
|  * This file is part of the lwIP TCP/IP stack. | ||||
|  * | ||||
|  * Author: Leon Woestenberg <leon.woestenberg@gmx.net> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_DHCP_H | ||||
| #define LWIP_HDR_PROT_DHCP_H | ||||
| 
 | ||||
| #include "lwip/opt.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define DHCP_CLIENT_PORT  68 | ||||
| #define DHCP_SERVER_PORT  67 | ||||
| 
 | ||||
| 
 | ||||
|  /* DHCP message item offsets and length */ | ||||
| #define DHCP_CHADDR_LEN   16U | ||||
| #define DHCP_SNAME_OFS    44U | ||||
| #define DHCP_SNAME_LEN    64U | ||||
| #define DHCP_FILE_OFS     108U | ||||
| #define DHCP_FILE_LEN     128U | ||||
| #define DHCP_MSG_LEN      236U | ||||
| #define DHCP_OPTIONS_OFS  (DHCP_MSG_LEN + 4U) /* 4 byte: cookie */ | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** minimum set of fields of any DHCP message */ | ||||
| struct dhcp_msg | ||||
| { | ||||
|   PACK_STRUCT_FLD_8(u8_t op); | ||||
|   PACK_STRUCT_FLD_8(u8_t htype); | ||||
|   PACK_STRUCT_FLD_8(u8_t hlen); | ||||
|   PACK_STRUCT_FLD_8(u8_t hops); | ||||
|   PACK_STRUCT_FIELD(u32_t xid); | ||||
|   PACK_STRUCT_FIELD(u16_t secs); | ||||
|   PACK_STRUCT_FIELD(u16_t flags); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t ciaddr); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t yiaddr); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t siaddr); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t giaddr); | ||||
|   PACK_STRUCT_FLD_8(u8_t chaddr[DHCP_CHADDR_LEN]); | ||||
|   PACK_STRUCT_FLD_8(u8_t sname[DHCP_SNAME_LEN]); | ||||
|   PACK_STRUCT_FLD_8(u8_t file[DHCP_FILE_LEN]); | ||||
|   PACK_STRUCT_FIELD(u32_t cookie); | ||||
| #define DHCP_MIN_OPTIONS_LEN 68U | ||||
| /** make sure user does not configure this too small */ | ||||
| #if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) | ||||
| #  undef DHCP_OPTIONS_LEN | ||||
| #endif | ||||
| /** allow this to be configured in lwipopts.h, but not too small */ | ||||
| #if (!defined(DHCP_OPTIONS_LEN)) | ||||
| /** set this to be sufficient for your options in outgoing DHCP msgs */ | ||||
| #  define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN | ||||
| #endif | ||||
|   PACK_STRUCT_FLD_8(u8_t options[DHCP_OPTIONS_LEN]); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* DHCP client states */ | ||||
| typedef enum { | ||||
|   DHCP_STATE_OFF             = 0, | ||||
|   DHCP_STATE_REQUESTING      = 1, | ||||
|   DHCP_STATE_INIT            = 2, | ||||
|   DHCP_STATE_REBOOTING       = 3, | ||||
|   DHCP_STATE_REBINDING       = 4, | ||||
|   DHCP_STATE_RENEWING        = 5, | ||||
|   DHCP_STATE_SELECTING       = 6, | ||||
|   DHCP_STATE_INFORMING       = 7, | ||||
|   DHCP_STATE_CHECKING        = 8, | ||||
|   DHCP_STATE_PERMANENT       = 9,  /* not yet implemented */ | ||||
|   DHCP_STATE_BOUND           = 10, | ||||
|   DHCP_STATE_RELEASING       = 11, /* not yet implemented */ | ||||
|   DHCP_STATE_BACKING_OFF     = 12 | ||||
| } dhcp_state_enum_t; | ||||
| 
 | ||||
| /* DHCP op codes */ | ||||
| #define DHCP_BOOTREQUEST            1 | ||||
| #define DHCP_BOOTREPLY              2 | ||||
| 
 | ||||
| /* DHCP message types */ | ||||
| #define DHCP_DISCOVER               1 | ||||
| #define DHCP_OFFER                  2 | ||||
| #define DHCP_REQUEST                3 | ||||
| #define DHCP_DECLINE                4 | ||||
| #define DHCP_ACK                    5 | ||||
| #define DHCP_NAK                    6 | ||||
| #define DHCP_RELEASE                7 | ||||
| #define DHCP_INFORM                 8 | ||||
| 
 | ||||
| /** DHCP hardware type, currently only ethernet is supported */ | ||||
| #define DHCP_HTYPE_ETH              1 | ||||
| 
 | ||||
| #define DHCP_MAGIC_COOKIE           0x63825363UL | ||||
| 
 | ||||
| /* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ | ||||
| 
 | ||||
| /* BootP options */ | ||||
| #define DHCP_OPTION_PAD             0 | ||||
| #define DHCP_OPTION_SUBNET_MASK     1 /* RFC 2132 3.3 */ | ||||
| #define DHCP_OPTION_ROUTER          3 | ||||
| #define DHCP_OPTION_DNS_SERVER      6 | ||||
| #define DHCP_OPTION_HOSTNAME        12 | ||||
| #define DHCP_OPTION_IP_TTL          23 | ||||
| #define DHCP_OPTION_MTU             26 | ||||
| #define DHCP_OPTION_BROADCAST       28 | ||||
| #define DHCP_OPTION_TCP_TTL         37 | ||||
| #define DHCP_OPTION_NTP             42 | ||||
| #define DHCP_OPTION_END             255 | ||||
| 
 | ||||
| /* DHCP options */ | ||||
| #define DHCP_OPTION_REQUESTED_IP    50 /* RFC 2132 9.1, requested IP address */ | ||||
| #define DHCP_OPTION_LEASE_TIME      51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ | ||||
| #define DHCP_OPTION_OVERLOAD        52 /* RFC2132 9.3, use file and/or sname field for options */ | ||||
| 
 | ||||
| #define DHCP_OPTION_MESSAGE_TYPE    53 /* RFC 2132 9.6, important for DHCP */ | ||||
| #define DHCP_OPTION_MESSAGE_TYPE_LEN 1 | ||||
| 
 | ||||
| #define DHCP_OPTION_SERVER_ID       54 /* RFC 2132 9.7, server IP address */ | ||||
| #define DHCP_OPTION_PARAMETER_REQUEST_LIST  55 /* RFC 2132 9.8, requested option types */ | ||||
| 
 | ||||
| #define DHCP_OPTION_MAX_MSG_SIZE    57 /* RFC 2132 9.10, message size accepted >= 576 */ | ||||
| #define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 | ||||
| 
 | ||||
| #define DHCP_OPTION_T1              58 /* T1 renewal time */ | ||||
| #define DHCP_OPTION_T2              59 /* T2 rebinding time */ | ||||
| #define DHCP_OPTION_US              60 | ||||
| #define DHCP_OPTION_CLIENT_ID       61 | ||||
| #define DHCP_OPTION_TFTP_SERVERNAME 66 | ||||
| #define DHCP_OPTION_BOOTFILE        67 | ||||
| 
 | ||||
| /* possible combinations of overloading the file and sname fields with options */ | ||||
| #define DHCP_OVERLOAD_NONE          0 | ||||
| #define DHCP_OVERLOAD_FILE          1 | ||||
| #define DHCP_OVERLOAD_SNAME         2 | ||||
| #define DHCP_OVERLOAD_SNAME_FILE    3 | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /*LWIP_HDR_PROT_DHCP_H*/ | ||||
|  | @ -0,0 +1,140 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * DNS - host name to IP address resolver. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Port to lwIP from uIP | ||||
|  * by Jim Pettinato April 2007 | ||||
|  * | ||||
|  * security fixes and more by Simon Goldschmidt | ||||
|  * | ||||
|  * uIP version Copyright (c) 2002-2003, Adam Dunkels. | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef LWIP_HDR_PROT_DNS_H | ||||
| #define LWIP_HDR_PROT_DNS_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** DNS server port address */ | ||||
| #ifndef DNS_SERVER_PORT | ||||
| #define DNS_SERVER_PORT           53 | ||||
| #endif | ||||
| 
 | ||||
| /* DNS field TYPE used for "Resource Records" */ | ||||
| #define DNS_RRTYPE_A              1     /* a host address */ | ||||
| #define DNS_RRTYPE_NS             2     /* an authoritative name server */ | ||||
| #define DNS_RRTYPE_MD             3     /* a mail destination (Obsolete - use MX) */ | ||||
| #define DNS_RRTYPE_MF             4     /* a mail forwarder (Obsolete - use MX) */ | ||||
| #define DNS_RRTYPE_CNAME          5     /* the canonical name for an alias */ | ||||
| #define DNS_RRTYPE_SOA            6     /* marks the start of a zone of authority */ | ||||
| #define DNS_RRTYPE_MB             7     /* a mailbox domain name (EXPERIMENTAL) */ | ||||
| #define DNS_RRTYPE_MG             8     /* a mail group member (EXPERIMENTAL) */ | ||||
| #define DNS_RRTYPE_MR             9     /* a mail rename domain name (EXPERIMENTAL) */ | ||||
| #define DNS_RRTYPE_NULL           10    /* a null RR (EXPERIMENTAL) */ | ||||
| #define DNS_RRTYPE_WKS            11    /* a well known service description */ | ||||
| #define DNS_RRTYPE_PTR            12    /* a domain name pointer */ | ||||
| #define DNS_RRTYPE_HINFO          13    /* host information */ | ||||
| #define DNS_RRTYPE_MINFO          14    /* mailbox or mail list information */ | ||||
| #define DNS_RRTYPE_MX             15    /* mail exchange */ | ||||
| #define DNS_RRTYPE_TXT            16    /* text strings */ | ||||
| #define DNS_RRTYPE_AAAA           28    /* IPv6 address */ | ||||
| #define DNS_RRTYPE_SRV            33    /* service location */ | ||||
| #define DNS_RRTYPE_ANY            255   /* any type */ | ||||
| 
 | ||||
| /* DNS field CLASS used for "Resource Records" */ | ||||
| #define DNS_RRCLASS_IN            1     /* the Internet */ | ||||
| #define DNS_RRCLASS_CS            2     /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ | ||||
| #define DNS_RRCLASS_CH            3     /* the CHAOS class */ | ||||
| #define DNS_RRCLASS_HS            4     /* Hesiod [Dyer 87] */ | ||||
| #define DNS_RRCLASS_ANY           255   /* any class */ | ||||
| #define DNS_RRCLASS_FLUSH         0x800 /* Flush bit */ | ||||
| 
 | ||||
| /* DNS protocol flags */ | ||||
| #define DNS_FLAG1_RESPONSE        0x80 | ||||
| #define DNS_FLAG1_OPCODE_STATUS   0x10 | ||||
| #define DNS_FLAG1_OPCODE_INVERSE  0x08 | ||||
| #define DNS_FLAG1_OPCODE_STANDARD 0x00 | ||||
| #define DNS_FLAG1_AUTHORATIVE     0x04 | ||||
| #define DNS_FLAG1_TRUNC           0x02 | ||||
| #define DNS_FLAG1_RD              0x01 | ||||
| #define DNS_FLAG2_RA              0x80 | ||||
| #define DNS_FLAG2_ERR_MASK        0x0f | ||||
| #define DNS_FLAG2_ERR_NONE        0x00 | ||||
| #define DNS_FLAG2_ERR_NAME        0x03 | ||||
| 
 | ||||
| #define DNS_HDR_GET_OPCODE(hdr) ((((hdr)->flags1) >> 3) & 0xF) | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** DNS message header */ | ||||
| struct dns_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t id); | ||||
|   PACK_STRUCT_FLD_8(u8_t flags1); | ||||
|   PACK_STRUCT_FLD_8(u8_t flags2); | ||||
|   PACK_STRUCT_FIELD(u16_t numquestions); | ||||
|   PACK_STRUCT_FIELD(u16_t numanswers); | ||||
|   PACK_STRUCT_FIELD(u16_t numauthrr); | ||||
|   PACK_STRUCT_FIELD(u16_t numextrarr); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| #define SIZEOF_DNS_HDR 12 | ||||
| 
 | ||||
| 
 | ||||
| /* Multicast DNS definitions */ | ||||
| 
 | ||||
| /** UDP port for multicast DNS queries */ | ||||
| #ifndef DNS_MQUERY_PORT | ||||
| #define DNS_MQUERY_PORT             5353 | ||||
| #endif | ||||
| 
 | ||||
| /* IPv4 group for multicast DNS queries: 224.0.0.251 */ | ||||
| #ifndef DNS_MQUERY_IPV4_GROUP_INIT | ||||
| #define DNS_MQUERY_IPV4_GROUP_INIT  IPADDR4_INIT_BYTES(224,0,0,251) | ||||
| #endif | ||||
| 
 | ||||
| /* IPv6 group for multicast DNS queries: FF02::FB */ | ||||
| #ifndef DNS_MQUERY_IPV6_GROUP_INIT | ||||
| #define DNS_MQUERY_IPV6_GROUP_INIT  IPADDR6_INIT_HOST(0xFF020000,0,0,0xFB) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_DNS_H */ | ||||
|  | @ -0,0 +1,91 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * ARP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_ETHARP_H | ||||
| #define LWIP_HDR_PROT_ETHARP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/prot/ethernet.h" | ||||
| #include "lwip/ip4_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #ifndef ETHARP_HWADDR_LEN | ||||
| #define ETHARP_HWADDR_LEN     ETH_HWADDR_LEN | ||||
| #endif | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** the ARP message, see RFC 826 ("Packet format") */ | ||||
| struct etharp_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t hwtype); | ||||
|   PACK_STRUCT_FIELD(u16_t proto); | ||||
|   PACK_STRUCT_FLD_8(u8_t  hwlen); | ||||
|   PACK_STRUCT_FLD_8(u8_t  protolen); | ||||
|   PACK_STRUCT_FIELD(u16_t opcode); | ||||
|   PACK_STRUCT_FLD_S(struct eth_addr shwaddr); | ||||
|   PACK_STRUCT_FLD_S(struct ip4_addr2 sipaddr); | ||||
|   PACK_STRUCT_FLD_S(struct eth_addr dhwaddr); | ||||
|   PACK_STRUCT_FLD_S(struct ip4_addr2 dipaddr); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #define SIZEOF_ETHARP_HDR 28 | ||||
| 
 | ||||
| /* ARP hwtype values */ | ||||
| enum etharp_hwtype { | ||||
|   HWTYPE_ETHERNET = 1 | ||||
|   /* others not used */ | ||||
| }; | ||||
| 
 | ||||
| /* ARP message types (opcodes) */ | ||||
| enum etharp_opcode { | ||||
|   ARP_REQUEST = 1, | ||||
|   ARP_REPLY   = 2 | ||||
| }; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_ETHARP_H */ | ||||
|  | @ -0,0 +1,164 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * Ethernet protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_ETHERNET_H | ||||
| #define LWIP_HDR_PROT_ETHERNET_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #ifndef ETH_HWADDR_LEN | ||||
| #ifdef ETHARP_HWADDR_LEN | ||||
| #define ETH_HWADDR_LEN    ETHARP_HWADDR_LEN /* compatibility mode */ | ||||
| #else | ||||
| #define ETH_HWADDR_LEN    6 | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct eth_addr { | ||||
|   PACK_STRUCT_FLD_8(u8_t addr[ETH_HWADDR_LEN]); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** Ethernet header */ | ||||
| struct eth_hdr { | ||||
| #if ETH_PAD_SIZE | ||||
|   PACK_STRUCT_FLD_8(u8_t padding[ETH_PAD_SIZE]); | ||||
| #endif | ||||
|   PACK_STRUCT_FLD_S(struct eth_addr dest); | ||||
|   PACK_STRUCT_FLD_S(struct eth_addr src); | ||||
|   PACK_STRUCT_FIELD(u16_t type); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE) | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /** VLAN header inserted between ethernet header and payload
 | ||||
|  * if 'type' in ethernet header is ETHTYPE_VLAN. | ||||
|  * See IEEE802.Q */ | ||||
| struct eth_vlan_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t prio_vid); | ||||
|   PACK_STRUCT_FIELD(u16_t tpid); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #define SIZEOF_VLAN_HDR 4 | ||||
| #define VLAN_ID(vlan_hdr) (lwip_htons((vlan_hdr)->prio_vid) & 0xFFF) | ||||
| 
 | ||||
| /**
 | ||||
|  * @ingroup ethernet | ||||
|  * A list of often ethtypes (although lwIP does not use all of them): */ | ||||
| enum eth_type { | ||||
|   /** Internet protocol v4 */ | ||||
|   ETHTYPE_IP        = 0x0800U, | ||||
|   /** Address resolution protocol */ | ||||
|   ETHTYPE_ARP       = 0x0806U,  | ||||
|   /** Wake on lan */ | ||||
|   ETHTYPE_WOL       = 0x0842U, | ||||
|   /** RARP */ | ||||
|   ETHTYPE_RARP      = 0x8035U, | ||||
|   /** Virtual local area network */ | ||||
|   ETHTYPE_VLAN      = 0x8100U, | ||||
|   /** Internet protocol v6 */ | ||||
|   ETHTYPE_IPV6      = 0x86DDU, | ||||
|   /** PPP Over Ethernet Discovery Stage */ | ||||
|   ETHTYPE_PPPOEDISC = 0x8863U, | ||||
|   /** PPP Over Ethernet Session Stage */ | ||||
|   ETHTYPE_PPPOE     = 0x8864U, | ||||
|   /** Jumbo Frames */ | ||||
|   ETHTYPE_JUMBO     = 0x8870U, | ||||
|   /** Process field network */ | ||||
|   ETHTYPE_PROFINET  = 0x8892U, | ||||
|   /** Ethernet for control automation technology */ | ||||
|   ETHTYPE_ETHERCAT  = 0x88A4U, | ||||
|   /** Link layer discovery protocol */ | ||||
|   ETHTYPE_LLDP      = 0x88CCU, | ||||
|   /** Serial real-time communication system */ | ||||
|   ETHTYPE_SERCOS    = 0x88CDU, | ||||
|   /** Media redundancy protocol */ | ||||
|   ETHTYPE_MRP       = 0x88E3U, | ||||
|   /** Precision time protocol */ | ||||
|   ETHTYPE_PTP       = 0x88F7U, | ||||
|   /** Q-in-Q, 802.1ad */ | ||||
|   ETHTYPE_QINQ      = 0x9100U | ||||
| }; | ||||
| 
 | ||||
| /** The 24-bit IANA IPv4-multicast OUI is 01-00-5e: */ | ||||
| #define LL_IP4_MULTICAST_ADDR_0 0x01 | ||||
| #define LL_IP4_MULTICAST_ADDR_1 0x00 | ||||
| #define LL_IP4_MULTICAST_ADDR_2 0x5e | ||||
| 
 | ||||
| /** IPv6 multicast uses this prefix */ | ||||
| #define LL_IP6_MULTICAST_ADDR_0 0x33 | ||||
| #define LL_IP6_MULTICAST_ADDR_1 0x33 | ||||
| 
 | ||||
| /** MEMCPY-like macro to copy to/from struct eth_addr's that are no local
 | ||||
|  * variables and known to be 16-bit aligned within the protocol header. */ | ||||
| #ifndef ETHADDR16_COPY | ||||
| #define ETHADDR16_COPY(dst, src)  SMEMCPY(dst, src, ETH_HWADDR_LEN) | ||||
| #endif | ||||
| 
 | ||||
| #define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETH_HWADDR_LEN) == 0) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_ETHERNET_H */ | ||||
|  | @ -0,0 +1,91 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * ICMP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_ICMP_H | ||||
| #define LWIP_HDR_PROT_ICMP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define ICMP_ER   0    /* echo reply */ | ||||
| #define ICMP_DUR  3    /* destination unreachable */ | ||||
| #define ICMP_SQ   4    /* source quench */ | ||||
| #define ICMP_RD   5    /* redirect */ | ||||
| #define ICMP_ECHO 8    /* echo */ | ||||
| #define ICMP_TE  11    /* time exceeded */ | ||||
| #define ICMP_PP  12    /* parameter problem */ | ||||
| #define ICMP_TS  13    /* timestamp */ | ||||
| #define ICMP_TSR 14    /* timestamp reply */ | ||||
| #define ICMP_IRQ 15    /* information request */ | ||||
| #define ICMP_IR  16    /* information reply */ | ||||
| #define ICMP_AM  17    /* address mask request */ | ||||
| #define ICMP_AMR 18    /* address mask reply */ | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| /** This is the standard ICMP header only that the u32_t data
 | ||||
|  *  is split to two u16_t like ICMP echo needs it. | ||||
|  *  This header is also used for other ICMP types that do not | ||||
|  *  use the data part. | ||||
|  */ | ||||
| PACK_STRUCT_BEGIN | ||||
| struct icmp_echo_hdr { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u16_t id); | ||||
|   PACK_STRUCT_FIELD(u16_t seqno); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Compatibility defines, old versions used to combine type and code to an u16_t */ | ||||
| #define ICMPH_TYPE(hdr) ((hdr)->type) | ||||
| #define ICMPH_CODE(hdr) ((hdr)->code) | ||||
| #define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) | ||||
| #define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_ICMP_H */ | ||||
|  | @ -0,0 +1,170 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * ICMP6 protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_ICMP6_H | ||||
| #define LWIP_HDR_PROT_ICMP6_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** ICMP type */ | ||||
| enum icmp6_type { | ||||
|   /** Destination unreachable */ | ||||
|   ICMP6_TYPE_DUR = 1, | ||||
|   /** Packet too big */ | ||||
|   ICMP6_TYPE_PTB = 2, | ||||
|   /** Time exceeded */ | ||||
|   ICMP6_TYPE_TE = 3, | ||||
|   /** Parameter problem */ | ||||
|   ICMP6_TYPE_PP = 4, | ||||
|   /** Private experimentation */ | ||||
|   ICMP6_TYPE_PE1 = 100, | ||||
|   /** Private experimentation */ | ||||
|   ICMP6_TYPE_PE2 = 101, | ||||
|   /** Reserved for expansion of error messages */ | ||||
|   ICMP6_TYPE_RSV_ERR = 127, | ||||
| 
 | ||||
|   /** Echo request */ | ||||
|   ICMP6_TYPE_EREQ = 128, | ||||
|   /** Echo reply */ | ||||
|   ICMP6_TYPE_EREP = 129, | ||||
|   /** Multicast listener query */ | ||||
|   ICMP6_TYPE_MLQ = 130, | ||||
|   /** Multicast listener report */ | ||||
|   ICMP6_TYPE_MLR = 131, | ||||
|   /** Multicast listener done */ | ||||
|   ICMP6_TYPE_MLD = 132, | ||||
|   /** Router solicitation */ | ||||
|   ICMP6_TYPE_RS = 133, | ||||
|   /** Router advertisement */ | ||||
|   ICMP6_TYPE_RA = 134, | ||||
|   /** Neighbor solicitation */ | ||||
|   ICMP6_TYPE_NS = 135, | ||||
|   /** Neighbor advertisement */ | ||||
|   ICMP6_TYPE_NA = 136, | ||||
|   /** Redirect */ | ||||
|   ICMP6_TYPE_RD = 137, | ||||
|   /** Multicast router advertisement */ | ||||
|   ICMP6_TYPE_MRA = 151, | ||||
|   /** Multicast router solicitation */ | ||||
|   ICMP6_TYPE_MRS = 152, | ||||
|   /** Multicast router termination */ | ||||
|   ICMP6_TYPE_MRT = 153, | ||||
|   /** Private experimentation */ | ||||
|   ICMP6_TYPE_PE3 = 200, | ||||
|   /** Private experimentation */ | ||||
|   ICMP6_TYPE_PE4 = 201, | ||||
|   /** Reserved for expansion of informational messages */ | ||||
|   ICMP6_TYPE_RSV_INF = 255 | ||||
| }; | ||||
| 
 | ||||
| /** ICMP destination unreachable codes */ | ||||
| enum icmp6_dur_code { | ||||
|   /** No route to destination */ | ||||
|   ICMP6_DUR_NO_ROUTE = 0, | ||||
|   /** Communication with destination administratively prohibited */ | ||||
|   ICMP6_DUR_PROHIBITED = 1, | ||||
|   /** Beyond scope of source address */ | ||||
|   ICMP6_DUR_SCOPE = 2, | ||||
|   /** Address unreachable */ | ||||
|   ICMP6_DUR_ADDRESS = 3, | ||||
|   /** Port unreachable */ | ||||
|   ICMP6_DUR_PORT = 4, | ||||
|   /** Source address failed ingress/egress policy */ | ||||
|   ICMP6_DUR_POLICY = 5, | ||||
|   /** Reject route to destination */ | ||||
|   ICMP6_DUR_REJECT_ROUTE = 6 | ||||
| }; | ||||
| 
 | ||||
| /** ICMP time exceeded codes */ | ||||
| enum icmp6_te_code { | ||||
|   /** Hop limit exceeded in transit */ | ||||
|   ICMP6_TE_HL = 0, | ||||
|   /** Fragment reassembly time exceeded */ | ||||
|   ICMP6_TE_FRAG = 1 | ||||
| }; | ||||
| 
 | ||||
| /** ICMP parameter code */ | ||||
| enum icmp6_pp_code { | ||||
|   /** Erroneous header field encountered */ | ||||
|   ICMP6_PP_FIELD = 0, | ||||
|   /** Unrecognized next header type encountered */ | ||||
|   ICMP6_PP_HEADER = 1, | ||||
|   /** Unrecognized IPv6 option encountered */ | ||||
|   ICMP6_PP_OPTION = 2 | ||||
| }; | ||||
| 
 | ||||
| /** This is the standard ICMP6 header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct icmp6_hdr { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u32_t data); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** This is the ICMP6 header adapted for echo req/resp. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct icmp6_echo_hdr { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u16_t id); | ||||
|   PACK_STRUCT_FIELD(u16_t seqno); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_ICMP6_H */ | ||||
|  | @ -0,0 +1,90 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * IGMP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_IGMP_H | ||||
| #define LWIP_HDR_PROT_IGMP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/ip4_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * IGMP constants | ||||
|  */ | ||||
| #define IGMP_TTL                       1 | ||||
| #define IGMP_MINLEN                    8 | ||||
| #define ROUTER_ALERT                   0x9404U | ||||
| #define ROUTER_ALERTLEN                4 | ||||
| 
 | ||||
| /*
 | ||||
|  * IGMP message types, including version number. | ||||
|  */ | ||||
| #define IGMP_MEMB_QUERY                0x11 /* Membership query         */ | ||||
| #define IGMP_V1_MEMB_REPORT            0x12 /* Ver. 1 membership report */ | ||||
| #define IGMP_V2_MEMB_REPORT            0x16 /* Ver. 2 membership report */ | ||||
| #define IGMP_LEAVE_GROUP               0x17 /* Leave-group message      */ | ||||
| 
 | ||||
| /* Group  membership states */ | ||||
| #define IGMP_GROUP_NON_MEMBER          0 | ||||
| #define IGMP_GROUP_DELAYING_MEMBER     1 | ||||
| #define IGMP_GROUP_IDLE_MEMBER         2 | ||||
| 
 | ||||
| /**
 | ||||
|  * IGMP packet format. | ||||
|  */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct igmp_msg { | ||||
|   PACK_STRUCT_FLD_8(u8_t         igmp_msgtype); | ||||
|   PACK_STRUCT_FLD_8(u8_t         igmp_maxresp); | ||||
|   PACK_STRUCT_FIELD(u16_t        igmp_checksum); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t igmp_group_address); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_IGMP_H */ | ||||
|  | @ -0,0 +1,51 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * IP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_IP_H | ||||
| #define LWIP_HDR_PROT_IP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #define IP_PROTO_ICMP    1 | ||||
| #define IP_PROTO_IGMP    2 | ||||
| #define IP_PROTO_UDP     17 | ||||
| #define IP_PROTO_UDPLITE 136 | ||||
| #define IP_PROTO_TCP     6 | ||||
| 
 | ||||
| /** This operates on a void* by loading the first byte */ | ||||
| #define IP_HDR_GET_VERSION(ptr)   ((*(u8_t*)(ptr)) >> 4) | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_IP_H */ | ||||
|  | @ -0,0 +1,127 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * IPv4 protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_IP4_H | ||||
| #define LWIP_HDR_PROT_IP4_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/ip4_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** This is the packed version of ip4_addr_t,
 | ||||
|     used in network headers that are itself packed */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ip4_addr_packed { | ||||
|   PACK_STRUCT_FIELD(u32_t addr); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| typedef struct ip4_addr_packed ip4_addr_p_t; | ||||
| 
 | ||||
| /* Size of the IPv4 header. Same as 'sizeof(struct ip_hdr)'. */ | ||||
| #define IP_HLEN 20 | ||||
| 
 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| /* The IPv4 header */ | ||||
| struct ip_hdr { | ||||
|   /* version / header length */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _v_hl); | ||||
|   /* type of service */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _tos); | ||||
|   /* total length */ | ||||
|   PACK_STRUCT_FIELD(u16_t _len); | ||||
|   /* identification */ | ||||
|   PACK_STRUCT_FIELD(u16_t _id); | ||||
|   /* fragment offset field */ | ||||
|   PACK_STRUCT_FIELD(u16_t _offset); | ||||
| #define IP_RF 0x8000U        /* reserved fragment flag */ | ||||
| #define IP_DF 0x4000U        /* don't fragment flag */ | ||||
| #define IP_MF 0x2000U        /* more fragments flag */ | ||||
| #define IP_OFFMASK 0x1fffU   /* mask for fragmenting bits */ | ||||
|   /* time to live */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _ttl); | ||||
|   /* protocol*/ | ||||
|   PACK_STRUCT_FLD_8(u8_t _proto); | ||||
|   /* checksum */ | ||||
|   PACK_STRUCT_FIELD(u16_t _chksum); | ||||
|   /* source and destination IP addresses */ | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t src); | ||||
|   PACK_STRUCT_FLD_S(ip4_addr_p_t dest); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Macros to get struct ip_hdr fields: */ | ||||
| #define IPH_V(hdr)  ((hdr)->_v_hl >> 4) | ||||
| #define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) | ||||
| #define IPH_TOS(hdr) ((hdr)->_tos) | ||||
| #define IPH_LEN(hdr) ((hdr)->_len) | ||||
| #define IPH_ID(hdr) ((hdr)->_id) | ||||
| #define IPH_OFFSET(hdr) ((hdr)->_offset) | ||||
| #define IPH_TTL(hdr) ((hdr)->_ttl) | ||||
| #define IPH_PROTO(hdr) ((hdr)->_proto) | ||||
| #define IPH_CHKSUM(hdr) ((hdr)->_chksum) | ||||
| 
 | ||||
| /* Macros to set struct ip_hdr fields: */ | ||||
| #define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) | ||||
| #define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) | ||||
| #define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) | ||||
| #define IPH_ID_SET(hdr, id) (hdr)->_id = (id) | ||||
| #define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) | ||||
| #define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) | ||||
| #define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) | ||||
| #define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_IP4_H */ | ||||
|  | @ -0,0 +1,169 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * IPv6 protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_IP6_H | ||||
| #define LWIP_HDR_PROT_IP6_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/ip6_addr.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|     | ||||
| /** This is the packed version of ip6_addr_t,
 | ||||
|     used in network headers that are itself packed */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ip6_addr_packed { | ||||
|   PACK_STRUCT_FIELD(u32_t addr[4]); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| typedef struct ip6_addr_packed ip6_addr_p_t; | ||||
| 
 | ||||
| #define IP6_HLEN 40 | ||||
| 
 | ||||
| #define IP6_NEXTH_HOPBYHOP  0 | ||||
| #define IP6_NEXTH_TCP       6 | ||||
| #define IP6_NEXTH_UDP       17 | ||||
| #define IP6_NEXTH_ENCAPS    41 | ||||
| #define IP6_NEXTH_ROUTING   43 | ||||
| #define IP6_NEXTH_FRAGMENT  44 | ||||
| #define IP6_NEXTH_ICMP6     58 | ||||
| #define IP6_NEXTH_NONE      59 | ||||
| #define IP6_NEXTH_DESTOPTS  60 | ||||
| #define IP6_NEXTH_UDPLITE   136 | ||||
| 
 | ||||
| /** The IPv6 header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ip6_hdr { | ||||
|   /** version / traffic class / flow label */ | ||||
|   PACK_STRUCT_FIELD(u32_t _v_tc_fl); | ||||
|   /** payload length */ | ||||
|   PACK_STRUCT_FIELD(u16_t _plen); | ||||
|   /** next header */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _nexth); | ||||
|   /** hop limit */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _hoplim); | ||||
|   /** source and destination IP addresses */ | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t src); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t dest); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Hop-by-hop router alert option. */ | ||||
| #define IP6_HBH_HLEN    8 | ||||
| #define IP6_PAD1_OPTION         0 | ||||
| #define IP6_PADN_ALERT_OPTION   1 | ||||
| #define IP6_ROUTER_ALERT_OPTION 5 | ||||
| #define IP6_ROUTER_ALERT_VALUE_MLD 0 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ip6_hbh_hdr { | ||||
|   /* next header */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _nexth); | ||||
|   /* header length */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _hlen); | ||||
|   /* router alert option type */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _ra_opt_type); | ||||
|   /* router alert option data len */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _ra_opt_dlen); | ||||
|   /* router alert option data */ | ||||
|   PACK_STRUCT_FIELD(u16_t _ra_opt_data); | ||||
|   /* PadN option type */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _padn_opt_type); | ||||
|   /* PadN option data len */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _padn_opt_dlen); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /* Fragment header. */ | ||||
| #define IP6_FRAG_HLEN    8 | ||||
| #define IP6_FRAG_OFFSET_MASK    0xfff8 | ||||
| #define IP6_FRAG_MORE_FLAG      0x0001 | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ip6_frag_hdr { | ||||
|   /* next header */ | ||||
|   PACK_STRUCT_FLD_8(u8_t _nexth); | ||||
|   /* reserved */ | ||||
|   PACK_STRUCT_FLD_8(u8_t reserved); | ||||
|   /* fragment offset */ | ||||
|   PACK_STRUCT_FIELD(u16_t _fragment_offset); | ||||
|   /* fragmented packet identification */ | ||||
|   PACK_STRUCT_FIELD(u32_t _identification); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #define IP6H_V(hdr)  ((lwip_ntohl((hdr)->_v_tc_fl) >> 28) & 0x0f) | ||||
| #define IP6H_TC(hdr) ((lwip_ntohl((hdr)->_v_tc_fl) >> 20) & 0xff) | ||||
| #define IP6H_FL(hdr) (lwip_ntohl((hdr)->_v_tc_fl) & 0x000fffff) | ||||
| #define IP6H_PLEN(hdr) (lwip_ntohs((hdr)->_plen)) | ||||
| #define IP6H_NEXTH(hdr) ((hdr)->_nexth) | ||||
| #define IP6H_NEXTH_P(hdr) ((u8_t *)(hdr) + 6) | ||||
| #define IP6H_HOPLIM(hdr) ((hdr)->_hoplim) | ||||
| 
 | ||||
| #define IP6H_VTCFL_SET(hdr, v, tc, fl) (hdr)->_v_tc_fl = (lwip_htonl((((u32_t)(v)) << 28) | (((u32_t)(tc)) << 20) | (fl))) | ||||
| #define IP6H_PLEN_SET(hdr, plen) (hdr)->_plen = lwip_htons(plen) | ||||
| #define IP6H_NEXTH_SET(hdr, nexth) (hdr)->_nexth = (nexth) | ||||
| #define IP6H_HOPLIM_SET(hdr, hl) (hdr)->_hoplim = (u8_t)(hl) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_IP6_H */ | ||||
|  | @ -0,0 +1,70 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * MLD6 protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_MLD6_H | ||||
| #define LWIP_HDR_PROT_MLD6_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/prot/ip6.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** Multicast listener report/query/done message header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct mld_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u16_t max_resp_delay); | ||||
|   PACK_STRUCT_FIELD(u16_t reserved); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t multicast_address); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_MLD6_H */ | ||||
|  | @ -0,0 +1,277 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * ND6 protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_ND6_H | ||||
| #define LWIP_HDR_PROT_ND6_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| #include "lwip/ip6_addr.h" | ||||
| #include "lwip/prot/ip6.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /** Neighbor solicitation message header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ns_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u32_t reserved); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Neighbor advertisement message header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct na_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FLD_8(u8_t flags); | ||||
|   PACK_STRUCT_FLD_8(u8_t reserved[3]); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| #define ND6_FLAG_ROUTER      (0x80) | ||||
| #define ND6_FLAG_SOLICITED   (0x40) | ||||
| #define ND6_FLAG_OVERRIDE    (0x20) | ||||
| 
 | ||||
| /** Router solicitation message header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct rs_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u32_t reserved); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Router advertisement message header. */ | ||||
| #define ND6_RA_FLAG_MANAGED_ADDR_CONFIG (0x80) | ||||
| #define ND6_RA_FLAG_OTHER_CONFIG (0x40) | ||||
| #define ND6_RA_FLAG_HOME_AGENT (0x20) | ||||
| #define ND6_RA_PREFERENCE_MASK (0x18) | ||||
| #define ND6_RA_PREFERENCE_HIGH (0x08) | ||||
| #define ND6_RA_PREFERENCE_MEDIUM (0x00) | ||||
| #define ND6_RA_PREFERENCE_LOW (0x18) | ||||
| #define ND6_RA_PREFERENCE_DISABLED (0x10) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct ra_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FLD_8(u8_t current_hop_limit); | ||||
|   PACK_STRUCT_FLD_8(u8_t flags); | ||||
|   PACK_STRUCT_FIELD(u16_t router_lifetime); | ||||
|   PACK_STRUCT_FIELD(u32_t reachable_time); | ||||
|   PACK_STRUCT_FIELD(u32_t retrans_timer); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Redirect message header. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct redirect_header { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t code); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u32_t reserved); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t target_address); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t destination_address); | ||||
|   /* Options follow. */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Link-layer address option. */ | ||||
| #define ND6_OPTION_TYPE_SOURCE_LLADDR (0x01) | ||||
| #define ND6_OPTION_TYPE_TARGET_LLADDR (0x02) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct lladdr_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FLD_8(u8_t addr[NETIF_MAX_HWADDR_LEN]); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Prefix information option. */ | ||||
| #define ND6_OPTION_TYPE_PREFIX_INFO (0x03) | ||||
| #define ND6_PREFIX_FLAG_ON_LINK (0x80) | ||||
| #define ND6_PREFIX_FLAG_AUTONOMOUS (0x40) | ||||
| #define ND6_PREFIX_FLAG_ROUTER_ADDRESS (0x20) | ||||
| #define ND6_PREFIX_FLAG_SITE_PREFIX (0x10) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct prefix_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FLD_8(u8_t prefix_length); | ||||
|   PACK_STRUCT_FLD_8(u8_t flags); | ||||
|   PACK_STRUCT_FIELD(u32_t valid_lifetime); | ||||
|   PACK_STRUCT_FIELD(u32_t preferred_lifetime); | ||||
|   PACK_STRUCT_FLD_8(u8_t reserved2[3]); | ||||
|   PACK_STRUCT_FLD_8(u8_t site_prefix_length); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Redirected header option. */ | ||||
| #define ND6_OPTION_TYPE_REDIR_HDR (0x04) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct redirected_header_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FLD_8(u8_t reserved[6]); | ||||
|   /* Portion of redirected packet follows. */ | ||||
|   /* PACK_STRUCT_FLD_8(u8_t redirected[8]); */ | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** MTU option. */ | ||||
| #define ND6_OPTION_TYPE_MTU (0x05) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct mtu_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FIELD(u16_t reserved); | ||||
|   PACK_STRUCT_FIELD(u32_t mtu); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Route information option. */ | ||||
| #define ND6_OPTION_TYPE_ROUTE_INFO (24) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct route_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FLD_8(u8_t prefix_length); | ||||
|   PACK_STRUCT_FLD_8(u8_t preference); | ||||
|   PACK_STRUCT_FIELD(u32_t route_lifetime); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t prefix); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /** Recursive DNS Server Option. */ | ||||
| #if LWIP_ND6_RDNSS_MAX_DNS_SERVERS | ||||
| #define LWIP_RDNSS_OPTION_MAX_SERVERS LWIP_ND6_RDNSS_MAX_DNS_SERVERS | ||||
| #else | ||||
| #define LWIP_RDNSS_OPTION_MAX_SERVERS 1 | ||||
| #endif | ||||
| #define ND6_OPTION_TYPE_RDNSS (25) | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct rdnss_option { | ||||
|   PACK_STRUCT_FLD_8(u8_t type); | ||||
|   PACK_STRUCT_FLD_8(u8_t length); | ||||
|   PACK_STRUCT_FIELD(u16_t reserved); | ||||
|   PACK_STRUCT_FIELD(u32_t lifetime); | ||||
|   PACK_STRUCT_FLD_S(ip6_addr_p_t rdnss_address[LWIP_RDNSS_OPTION_MAX_SERVERS]); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_ND6_H */ | ||||
|  | @ -0,0 +1,97 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * TCP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_TCP_H | ||||
| #define LWIP_HDR_PROT_TCP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* Length of the TCP header, excluding options. */ | ||||
| #define TCP_HLEN 20 | ||||
| 
 | ||||
| /* Fields are (of course) in network byte order.
 | ||||
|  * Some fields are converted to host byte order in tcp_input(). | ||||
|  */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct tcp_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t src); | ||||
|   PACK_STRUCT_FIELD(u16_t dest); | ||||
|   PACK_STRUCT_FIELD(u32_t seqno); | ||||
|   PACK_STRUCT_FIELD(u32_t ackno); | ||||
|   PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags); | ||||
|   PACK_STRUCT_FIELD(u16_t wnd); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
|   PACK_STRUCT_FIELD(u16_t urgp); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| /* TCP header flags bits */ | ||||
| #define TCP_FIN 0x01U | ||||
| #define TCP_SYN 0x02U | ||||
| #define TCP_RST 0x04U | ||||
| #define TCP_PSH 0x08U | ||||
| #define TCP_ACK 0x10U | ||||
| #define TCP_URG 0x20U | ||||
| #define TCP_ECE 0x40U | ||||
| #define TCP_CWR 0x80U | ||||
| /* Valid TCP header flags */ | ||||
| #define TCP_FLAGS 0x3fU | ||||
| 
 | ||||
| #define TCPH_HDRLEN(phdr) ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)) | ||||
| #define TCPH_FLAGS(phdr)  ((u16_t)(lwip_ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)) | ||||
| 
 | ||||
| #define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = lwip_htons(((len) << 12) | TCPH_FLAGS(phdr)) | ||||
| #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS(~TCP_FLAGS)) | lwip_htons(flags)) | ||||
| #define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = (u16_t)(lwip_htons((u16_t)((len) << 12) | (flags))) | ||||
| 
 | ||||
| #define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | lwip_htons(flags)) | ||||
| #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags & ~lwip_htons(flags)) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_TCP_H */ | ||||
|  | @ -0,0 +1,68 @@ | |||
| /**
 | ||||
|  * @file | ||||
|  * UDP protocol definitions | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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: Adam Dunkels <adam@sics.se> | ||||
|  * | ||||
|  */ | ||||
| #ifndef LWIP_HDR_PROT_UDP_H | ||||
| #define LWIP_HDR_PROT_UDP_H | ||||
| 
 | ||||
| #include "lwip/arch.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #define UDP_HLEN 8 | ||||
| 
 | ||||
| /* Fields are (of course) in network byte order. */ | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/bpstruct.h" | ||||
| #endif | ||||
| PACK_STRUCT_BEGIN | ||||
| struct udp_hdr { | ||||
|   PACK_STRUCT_FIELD(u16_t src); | ||||
|   PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */ | ||||
|   PACK_STRUCT_FIELD(u16_t len); | ||||
|   PACK_STRUCT_FIELD(u16_t chksum); | ||||
| } PACK_STRUCT_STRUCT; | ||||
| PACK_STRUCT_END | ||||
| #ifdef PACK_STRUCT_USE_INCLUDES | ||||
| #  include "arch/epstruct.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* LWIP_HDR_PROT_UDP_H */ | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -96,24 +96,54 @@ VOID ShowRamBuildInfo(VOID) | |||
|     */ | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_APP_DEMO | ||||
| #include "device.h" | ||||
| #include "gpio_api.h"   // mbed | ||||
| #if 1 //def CONFIG_APP_DEMO
 | ||||
| #include "rtl8195a.h" | ||||
| //#include "device.h"
 | ||||
| //#include "gpio_api.h"   // mbed
 | ||||
| typedef struct _UART_LOG_BUF_ { | ||||
|         u8  BufCount;                           //record the input cmd char number.
 | ||||
|         u8  UARTLogBuf[127];   //record the input command.
 | ||||
| } UART_LOG_BUF, *PUART_LOG_BUF; | ||||
| 
 | ||||
| //MON_RAM_BSS_SECTION
 | ||||
| typedef struct _UART_LOG_CTL_ { | ||||
|         u8  NewIdx;		//+0
 | ||||
|         u8  SeeIdx;		//+1
 | ||||
|         u8  RevdNo;		//+2
 | ||||
|         u8  EscSTS;		//+3
 | ||||
|         u8  ExecuteCmd;	//+4
 | ||||
|         u8  ExecuteEsc; //+5
 | ||||
|         u8  BootRdy;	//+6
 | ||||
|         u8  Resvd;		//+7
 | ||||
|         PUART_LOG_BUF   pTmpLogBuf; | ||||
|         VOID *pfINPUT; | ||||
|         PCOMMAND_TABLE  pCmdTbl; | ||||
|         u32 CmdTblSz; | ||||
| 
 | ||||
|         u32  CRSTS; | ||||
| 
 | ||||
|         u8  (*pHistoryBuf)[127]; | ||||
| 
 | ||||
| 		u32	TaskRdy; | ||||
| 		u32	Sema; | ||||
| } UART_LOG_CTL, *PUART_LOG_CTL; | ||||
| 
 | ||||
| extern volatile UART_LOG_CTL *pUartLogCtl; | ||||
| 
 | ||||
| _WEAK int main(void) | ||||
| { | ||||
| 	HalPinCtrlRtl8195A(JTAG, 0, 1); | ||||
| 
 | ||||
| 	DiagPrintf("\r\nRTL Console ROM: Start - press key 'Up', Help '?'\r\n"); | ||||
| 	while(pUartLogCtl[5] != 1); | ||||
| 	pUartLogCtl[3] = 0; | ||||
| 	pUartLogCtl[6] = 1; | ||||
| 	while(pUartLogCtl->ExecuteEsc != 1); | ||||
| 	pUartLogCtl->RevdNo = 0; | ||||
| 	pUartLogCtl->BootRdy = 1; | ||||
|     DiagPrintf("\r<RTL8710AF>"); | ||||
|     while(1) { | ||||
|     	while(pUartLogCtl[4] != 1 ); | ||||
|     	while(pUartLogCtl->ExecuteCmd != 1 ); | ||||
|     	UartLogCmdExecute(pUartLogCtl); | ||||
|         DiagPrintf("\r<RTL8710AF>"); | ||||
|         pUartLogCtl[4] = 0; | ||||
|         pUartLogCtl->ExecuteCmd = 0; | ||||
|     } | ||||
|      | ||||
|     return 0; | ||||
|  | @ -190,6 +220,7 @@ void _AppStart(void) | |||
|     xTaskCreate( (TaskFunction_t)main, "MAIN_APP__TASK", (MAIN_APP_DEFAULT_STACK_SIZE/4), (void *)NULL, MAIN_APP_DEFAULT_PRIORITY, NULL); | ||||
|     vTaskStartScheduler(); | ||||
| #endif | ||||
| 
 | ||||
| #else | ||||
| 	 | ||||
| 	__low_level_init();		 | ||||
|  |  | |||
|  | @ -48,7 +48,6 @@ | |||
| //#define __SYSTEM_CLOCK    (5*__XTAL)
 | ||||
| #define __SYSTEM_CLOCK    (200000000UL/6*5) // PLATFORM_CLOCK // 
 | ||||
| 
 | ||||
| extern unsigned int rand_x; | ||||
| //extern u32 HalGetCpuClk(VOID);
 | ||||
| 
 | ||||
| #ifdef CONFIG_CHIP_A_CUT | ||||
|  | @ -62,6 +61,8 @@ const u32 SysCpkClkTbl[]= { | |||
| }; | ||||
| #endif | ||||
| 
 | ||||
| unsigned int rand_x = 12345; | ||||
| 
 | ||||
| u32 Rand2(void) | ||||
| { | ||||
|     static unsigned int y = 362436; | ||||
|  |  | |||
|  | @ -244,7 +244,7 @@ HAL_GPIO_IP_DeInit( | |||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //extern u16 GPIOState[_PORT_MAX-1]; // побитно 16 бит для каждого порта (A..K), бит=номер задействованного пина в порту на периферию.
 | ||||
| extern u16 GPIOState[_PORT_MAX]; // побитно 16 бит для каждого порта (A..K), бит=номер задействованного пина в порту на периферию.
 | ||||
| 
 | ||||
| #endif  // end of "#define _HAL_GPIO_H_"
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,12 +16,6 @@ | |||
| 
 | ||||
| #define SYSTEM_CLK                  PLATFORM_CLOCK | ||||
| 
 | ||||
| #define SDR_SDRAM_BASE              0x30000000 | ||||
| #define SYSTEM_CTRL_BASE            0x40000000 | ||||
| #define PERI_ON_BASE                0x40000000 | ||||
| #define VENDOR_REG_BASE             0x40002800 | ||||
| #define SPI_FLASH_BASE              0x98000000 | ||||
| #define SDR_CTRL_BASE               0x40005000 | ||||
| 
 | ||||
| #define PERIPHERAL_IRQ_STATUS       0x04 | ||||
| #define PERIPHERAL_IRQ_MODE         0x08 | ||||
|  | @ -34,13 +28,21 @@ | |||
| 
 | ||||
| #define TIMER_CLK                   32*1000 | ||||
| 
 | ||||
| #define SDR_SDRAM_BASE              0x30000000 | ||||
| #define SYSTEM_CTRL_BASE            0x40000000 | ||||
| #define PERI_ON_BASE                0x40000000 | ||||
| #define SPI_FLASH_BASE              0x98000000 | ||||
| 
 | ||||
| //3 Peripheral IP Base Address
 | ||||
| 
 | ||||
| #define GPIO_REG_BASE               0x40001000 | ||||
| #define TIMER_REG_BASE              0x40002000 | ||||
| #define VENDOR_REG_BASE             0x40002800 | ||||
| #define NFC_INTERFACE_BASE          0x40002400 | ||||
| #define LOG_UART_REG_BASE           0x40003000 | ||||
| #define I2C2_REG_BASE               0x40003400 | ||||
| #define I2C3_REG_BASE               0x40003800 | ||||
| #define SDR_CTRL_BASE               0x40005000 | ||||
| #define SPI_FLASH_CTRL_BASE         0x40006000 | ||||
| #define ADC_REG_BASE                0x40010000 | ||||
| #define DAC_REG_BASE                0x40011000 | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| #ifndef _HAL_SDR_CONTROLLER_H_ | ||||
| #define _HAL_SDR_CONTROLLER_H_ | ||||
| 
 | ||||
| #if 1 // def CONFIG_SDR_EN
 | ||||
| #if 1 //def CONFIG_SDR_EN
 | ||||
| 
 | ||||
| typedef enum _DRAM_TYPE_ { | ||||
|   DRAM_DDR_1 = 1, | ||||
|  | @ -187,5 +187,5 @@ typedef struct _DRAM_DEVICE_INFO_ { | |||
| #define HAL_SDRAM_READ8(addr)             HAL_READ8(SDR_SDRAM_BASE, addr) | ||||
| 
 | ||||
| #endif // CONFIG_SDR_EN
 | ||||
| // extern unsigned int rand_x; // in rtl_bios_data.h
 | ||||
| //extern unsigned int rand_x;
 | ||||
| #endif  // end of "#ifndef _HAL_SDR_CONTROLLER_H_"
 | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ enum _SPIC_BIT_MODE_ { | |||
| #define FLASH_EON 5 | ||||
| 
 | ||||
| //#define FLASH_MXIC_MX25L4006E   0
 | ||||
| //#define FLASH_MXIC_MX25L8073E   0
 | ||||
| //#define FLASH_MXIC_MX25L8073E   1
 | ||||
| //#define FLASH_MICRON_N25Q512A 1
 | ||||
| // The below parts are based on the flash characteristics
 | ||||
| //====== Flash Command Definition  ======
 | ||||
|  | @ -244,6 +244,7 @@ enum _SPIC_BIT_MODE_ { | |||
| 
 | ||||
| 
 | ||||
| //#endif
 | ||||
| 
 | ||||
| #if 0 | ||||
| #if FLASH_MXIC_MX25L4006E | ||||
| #define FLASH_RD_2IO_EN         1 | ||||
|  |  | |||
|  | @ -0,0 +1,130 @@ | |||
| /*
 | ||||
|  *  Routines to access hardware | ||||
|  * | ||||
|  *  Copyright (c) 2015 Realtek Semiconductor Corp. | ||||
|  * | ||||
|  *  This module is a confidential and proprietary property of RealTek and | ||||
|  *  possession or use of this module requires written permission of RealTek. | ||||
|  */ | ||||
| 
 | ||||
| #include "rtl8195a.h" | ||||
| #include "build_info.h" | ||||
| #include "PinNames.h" | ||||
| #include "serial_api.h" | ||||
| 
 | ||||
| extern void serial_init       (serial_t *obj, PinName tx, PinName rx); | ||||
| extern void serial_free       (serial_t *obj); | ||||
| extern void serial_baud       (serial_t *obj, int baudrate); | ||||
| extern void serial_format     (serial_t *obj, int data_bits, SerialParity parity, int stop_bits); | ||||
| extern int main(void); | ||||
| 
 | ||||
| void iar_data_init_fw_loader(void); | ||||
| void fw_loader_main(void);// __attribute__ ((weak));
 | ||||
| 
 | ||||
| #pragma section=".image2.start.table1" | ||||
| #pragma section=".fwloader_ram.bss" | ||||
| 
 | ||||
| FW_LOADER_START_RAM_FUN_SECTION | ||||
| RAM_START_FUNCTION gFWLoaderEntryFun0 = {fw_loader_main}; | ||||
| 
 | ||||
| u8* __image4_entry_func__; | ||||
| u8* __image4_validate_code__; | ||||
| u8* __fwloader_bss_start__; | ||||
| u8* __fwloader_bss_end__; | ||||
| 
 | ||||
| FW_LOADER_VALID_PATTEN_SECTION const u8 RAM_FW_LOADER_VALID_PATTEN[20] = { | ||||
|     'R', 'T', 'K', 'W', 'i', 'n', 0x0, 0xff,  | ||||
|     (FW_VERSION&0xff), ((FW_VERSION >> 8)&0xff), | ||||
|     (FW_SUBVERSION&0xff), ((FW_SUBVERSION >> 8)&0xff), | ||||
|     (FW_CHIP_ID&0xff), ((FW_CHIP_ID >> 8)&0xff), | ||||
|     (FW_CHIP_VER), | ||||
|     (FW_BUS_TYPE), | ||||
|     (FW_INFO_RSV1), | ||||
|     (FW_INFO_RSV2), | ||||
|     (FW_INFO_RSV3), | ||||
|     (FW_INFO_RSV4)     | ||||
| }; | ||||
| /**
 | ||||
|   * @brief  Main program. | ||||
|   * @param  None | ||||
|   * @retval None | ||||
|   */   | ||||
| void fw_loader_main(void) | ||||
| { | ||||
| #if defined ( __ICCARM__ )    | ||||
| 	iar_data_init_fw_loader(); | ||||
| #endif	 | ||||
|       	u32 Image2Len, Image2Addr, ImageIndex, SpicBitMode, SpicImageIndex; | ||||
|       	u32 Image2LoadAddr = 0x13000; | ||||
| 	DBG_8195A("===== Enter FW Loader Image  ====\n"); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef BOOTLOADER | ||||
|      main(); | ||||
| #endif | ||||
| 
 | ||||
| IGMAE4: | ||||
| 	PRAM_START_FUNCTION Image4EntryFun=(PRAM_START_FUNCTION)__image4_entry_func__; | ||||
| 
 | ||||
| 	Image2Len = HAL_READ32(SPI_FLASH_BASE, Image2LoadAddr); | ||||
|     	Image2Addr = HAL_READ32(SPI_FLASH_BASE, (Image2LoadAddr+0x4)); | ||||
| 
 | ||||
|     	DBG_8195A("Flash FW Loader:Addr 0x%x, Len %d, Load to SRAM 0x%x\n", Image2LoadAddr, Image2Len, Image2Addr); | ||||
| 
 | ||||
|     	SpicImageIndex = 0; | ||||
|     	for (ImageIndex = 0x10 + Image2LoadAddr; ImageIndex < (Image2Len + Image2LoadAddr + 0x10); ImageIndex = ImageIndex + 4) { | ||||
| 		HAL_WRITE32(Image2Addr, SpicImageIndex, | ||||
| 	                HAL_READ32(SPI_FLASH_BASE, ImageIndex)); | ||||
| 
 | ||||
|       		SpicImageIndex += 4; | ||||
|     	}	 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONFIG_SDR_EN | ||||
|     u32 Image3LoadAddr; | ||||
|     u32 Image3Len; | ||||
|     u32 Image3Addr; | ||||
| 
 | ||||
|     Image3LoadAddr = Image2LoadAddr + Image2Len+0x10; | ||||
|     Image3Len = HAL_READ32(SPI_FLASH_BASE, Image3LoadAddr); | ||||
|     Image3Addr = HAL_READ32(SPI_FLASH_BASE, Image3LoadAddr + 0x4); | ||||
| 
 | ||||
| 	if( (Image3Len==0xFFFFFFFF) || (Image3Len==0) || (Image3Addr!=0x30000000)){ | ||||
| 		DBG_8195A("No Image3\n\r"); | ||||
| 	}else{ | ||||
| 		DBG_8195A("Image3 length: 0x%x, Image3 Addr: 0x%x\n",Image3Len, Image3Addr); | ||||
| 		SpicImageIndex = 0; | ||||
| 
 | ||||
| 		for (ImageIndex = 0x10 + Image3LoadAddr;  | ||||
| 				ImageIndex < (Image3Len + Image3LoadAddr + 0x10); | ||||
| 				ImageIndex = ImageIndex + 4) { | ||||
| 			HAL_WRITE32(Image3Addr, SpicImageIndex, | ||||
| 						HAL_READ32(SPI_FLASH_BASE, ImageIndex)); | ||||
| 
 | ||||
| 			SpicImageIndex += 4; | ||||
| 		} | ||||
| 	} | ||||
| #endif	 | ||||
|     //3 	3) Jump to image 4
 | ||||
|     	DBG_8195A("InfraStart: %p, Img2 Sign %s \n", __image4_entry_func__, (char*)__image4_validate_code__); | ||||
|     	if (_strcmp((char *)__image4_validate_code__, "RTKWin")) { | ||||
|       		while (1) { | ||||
|               	DBG_8195A("Invalid Image4 Signature\n"); | ||||
|             		RtlConsolRom(1000);//each delay is 100us
 | ||||
|         	} | ||||
|     	} | ||||
| 		 | ||||
| #ifdef BOOTLOADER | ||||
|       deinit_platform_bootloader();			 | ||||
| #endif | ||||
|     	Image4EntryFun->RamStartFun();	 | ||||
| } | ||||
| 
 | ||||
| void iar_data_init_fw_loader(void) | ||||
| { | ||||
|     __image4_entry_func__    =  (u8*)__section_begin(".image2.start.table1"); | ||||
| 	__image4_validate_code__	= __image4_entry_func__+4;//(u8*)__section_begin(".image2.start.table2");
 | ||||
| 	__fwloader_bss_start__		= (u8*)__section_begin(".fwloader_ram.bss"); | ||||
| 	__fwloader_bss_end__			= (u8*)__section_end(".fwloader_ram.bss");	 | ||||
| } | ||||
|  | @ -0,0 +1,82 @@ | |||
| /* 
 | ||||
| 	decompiled low_level_io.o | ||||
| */ | ||||
| #include ...... | ||||
| //-------------------------------------------------------------------------
 | ||||
| // Function declarations
 | ||||
| void mode_init(); | ||||
| void HalSerialPutcRtl8195a(int c, int a2, char a3); | ||||
| signed int DiagPrintf(const char *fmt, ...); | ||||
| void log_uart_enable_printf(); | ||||
| void log_uart_disable_printf(); | ||||
| //-------------------------------------------------------------------------
 | ||||
| // Data declarations
 | ||||
| uint32_t backupWarn; | ||||
| uint32_t backupErr; | ||||
| uint32_t backupInfo; | ||||
| int disablePrintf; | ||||
| // extern _UNKNOWN use_mode;
 | ||||
| // extern _UNKNOWN ConfigDebugErr;
 | ||||
| // extern _UNKNOWN ConfigDebugInfo;
 | ||||
| // extern _UNKNOWN ConfigDebugWarn;
 | ||||
| 
 | ||||
| //----- 
 | ||||
| void mode_init() | ||||
| { | ||||
|   use_mode = 1; | ||||
| } | ||||
| 
 | ||||
| //----- 
 | ||||
| void HalSerialPutcRtl8195a(int c) | ||||
| { | ||||
|   signed int v3; // r3@2
 | ||||
| 
 | ||||
|   if ( disablePrintf != 1 ) | ||||
|   { | ||||
|     v3 = 6540; | ||||
|     do | ||||
|     { | ||||
|       if ( !--v3 ) | ||||
|         break; | ||||
|       a3 = v40003014; | ||||
|     } | ||||
|     while ( !(v40003014 & 0x60) ); | ||||
|     if ( c == 10 ) a3 = 13; | ||||
|     v40003000 = c; | ||||
|     if ( c == 10 ) v40003000 = a3; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| //-----
 | ||||
| signed int DiagPrintf(const char *fmt, ...) | ||||
| { | ||||
|   va_list va; | ||||
| 
 | ||||
|   va_start(va, fmt); | ||||
|   if ( disablePrintf != 1 ) | ||||
|     VSprintf(0, fmt, va); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| //-----
 | ||||
| void log_uart_enable_printf() | ||||
| { | ||||
|   disablePrintf = 0; | ||||
|   ConfigDebugErr = backupErr; | ||||
|   ConfigDebugInfo = backupInfo; | ||||
|   ConfigDebugWarn = backupWarn; | ||||
| } | ||||
| 
 | ||||
| //-----
 | ||||
| void log_uart_disable_printf() | ||||
| { | ||||
|   disablePrintf = 1; | ||||
|   backupErr = ConfigDebugErr; | ||||
|   backupInfo = ConfigDebugInfo; | ||||
|   backupWarn = ConfigDebugWarn; | ||||
|   ConfigDebugErr = 0; | ||||
|   ConfigDebugInfo = 0; | ||||
|   ConfigDebugWarn = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -911,30 +911,30 @@ | |||
| #define BIT_CTRL_FLUSH_FIFO(x)                	(((x) & BIT_MASK_FLUSH_FIFO) << BIT_SHIFT_FLUSH_FIFO) | ||||
| 
 | ||||
| //=================== Register Address Definition ============================//
 | ||||
| #define REG_SPIC_CTRLR0 0x0000//O
 | ||||
| #define REG_SPIC_CTRLR1 0x0004//O
 | ||||
| #define REG_SPIC_SSIENR 0x0008//O
 | ||||
| #define REG_SPIC_MWCR 0x000C | ||||
| #define REG_SPIC_SER 0x0010//O
 | ||||
| #define REG_SPIC_BAUDR 0x0014//O
 | ||||
| #define REG_SPIC_TXFTLR 0x0018 | ||||
| #define REG_SPIC_RXFTLR 0x001C//O
 | ||||
| #define REG_SPIC_TXFLR 0x0020//O
 | ||||
| #define REG_SPIC_RXFLR 0x0024 | ||||
| #define REG_SPIC_SR 0x0028 | ||||
| #define REG_SPIC_IMR 0x002C//O
 | ||||
| #define REG_SPIC_ISR 0x0030 | ||||
| #define REG_SPIC_RISR 0x0034 | ||||
| #define REG_SPIC_TXOICR 0x0038 | ||||
| #define REG_SPIC_RXOICR 0x003C | ||||
| #define REG_SPC_RXUICR 0x0040 | ||||
| #define REG_SPIC_MSTICR 0x0044 | ||||
| #define REG_SPIC_ICR 0x0048 | ||||
| #define REG_SPIC_DMACR 0x004C | ||||
| #define REG_SPIC_DMATDLR0 0x0050 | ||||
| #define REG_SPIC_DMATDLR1 0x0054 | ||||
| #define REG_SPIC_IDR 0x0058 | ||||
| #define REG_SPIC_VERSION 0x005C | ||||
| #define REG_SPIC_CTRLR0 0x0000	//O	0x1040300
 | ||||
| #define REG_SPIC_CTRLR1 0x0004	//O 0x10
 | ||||
| #define REG_SPIC_SSIENR 0x0008	//O 0
 | ||||
| #define REG_SPIC_MWCR 0x000C	// 0
 | ||||
| #define REG_SPIC_SER 0x0010		//O 1
 | ||||
| #define REG_SPIC_BAUDR 0x0014	//O 1
 | ||||
| #define REG_SPIC_TXFTLR 0x0018	// 0
 | ||||
| #define REG_SPIC_RXFTLR 0x001C	//O 0x1F
 | ||||
| #define REG_SPIC_TXFLR 0x0020	//O 0
 | ||||
| #define REG_SPIC_RXFLR 0x0024	// 0
 | ||||
| #define REG_SPIC_SR 0x0028		// 6
 | ||||
| #define REG_SPIC_IMR 0x002C		//O 0x1FF
 | ||||
| #define REG_SPIC_ISR 0x0030		// 4
 | ||||
| #define REG_SPIC_RISR 0x0034	// 4
 | ||||
| #define REG_SPIC_TXOICR 0x0038	// 0
 | ||||
| #define REG_SPIC_RXOICR 0x003C	// 0
 | ||||
| #define REG_SPC_RXUICR 0x0040	// 0
 | ||||
| #define REG_SPIC_MSTICR 0x0044	// 0
 | ||||
| #define REG_SPIC_ICR 0x0048		// 0
 | ||||
| #define REG_SPIC_DMACR 0x004C	// 0
 | ||||
| #define REG_SPIC_DMATDLR0 0x0050	// 0
 | ||||
| #define REG_SPIC_DMATDLR1 0x0054	// 0
 | ||||
| #define REG_SPIC_IDR 0x0058		// 0x10001
 | ||||
| #define REG_SPIC_VERSION 0x005C	// 0x40470603
 | ||||
| #define REG_SPIC_DR0 0x0060 | ||||
| #define REG_SPIC_DR1 0x0064 | ||||
| #define REG_SPIC_DR2 0x0068 | ||||
|  | @ -966,26 +966,26 @@ | |||
| #define REG_SPIC_DR28 0x00D0 | ||||
| #define REG_SPIC_DR29 0x00D4 | ||||
| #define REG_SPIC_DR30 0x00D8 | ||||
| #define REG_SPIC_DR31 0x00DC | ||||
| #define REG_SPIC_READ_FAST_SINGLE 0x00E0//O
 | ||||
| #define REG_SPIC_READ_DUAL_DATA 0x00E4//O
 | ||||
| #define REG_SPIC_READ_DUAL_ADDR_DATA 0x00E8//O
 | ||||
| #define REG_SPIC_READ_QUAD_DATA 0x00EC//O
 | ||||
| #define REG_SPIC_READ_QUAD_ADDR_DATA 0x00F0//O
 | ||||
| #define REG_SPIC_WRITE_SIGNLE 0x00F4//O
 | ||||
| #define REG_SPIC_WRITE_DUAL_DATA 0x00F8//O
 | ||||
| #define REG_SPIC_WRITE_DUAL_ADDR_DATA 0x00FC//O
 | ||||
| #define REG_SPIC_WRITE_QUAD_DATA 0x0100//O
 | ||||
| #define REG_SPIC_WRITE_QUAD_ADDR_DATA 0x0104//O
 | ||||
| #define REG_SPIC_WRITE_ENABLE 0x0108//O
 | ||||
| #define REG_SPIC_READ_STATUS 0x010C//O
 | ||||
| #define REG_SPIC_CTRLR2 0x0110//O
 | ||||
| #define REG_SPIC_FBAUDR 0x0114//O
 | ||||
| #define REG_SPIC_ADDR_LENGTH 0x0118//O
 | ||||
| #define REG_SPIC_AUTO_LENGTH 0x011C//O
 | ||||
| #define REG_SPIC_VALID_CMD 0x0120//O
 | ||||
| #define REG_SPIC_FLASE_SIZE 0x0124//O
 | ||||
| #define REG_SPIC_FLUSH_FIFO 0x0128//O
 | ||||
| #define REG_SPIC_DR31 0x00DC				//  MXIC (DeviceID: FC, Flash Size: 1048576 bytes, FlashID: C22014/1,  SpicMode: DIO)
 | ||||
| #define REG_SPIC_READ_FAST_SINGLE 0x00E0	//O 0x0B
 | ||||
| #define REG_SPIC_READ_DUAL_DATA 0x00E4		//O 0x3B
 | ||||
| #define REG_SPIC_READ_DUAL_ADDR_DATA 0x00E8	//O 0x3B
 | ||||
| #define REG_SPIC_READ_QUAD_DATA 0x00EC		//O 0x6B
 | ||||
| #define REG_SPIC_READ_QUAD_ADDR_DATA 0x00F0	//O 0xEB
 | ||||
| #define REG_SPIC_WRITE_SIGNLE 0x00F4		//O 0x02
 | ||||
| #define REG_SPIC_WRITE_DUAL_DATA 0x00F8		//O 0xA2
 | ||||
| #define REG_SPIC_WRITE_DUAL_ADDR_DATA 0x00FC//O 0xA2
 | ||||
| #define REG_SPIC_WRITE_QUAD_DATA 0x0100		//O 0x32
 | ||||
| #define REG_SPIC_WRITE_QUAD_ADDR_DATA 0x0104//O 0x38
 | ||||
| #define REG_SPIC_WRITE_ENABLE 0x0108		//O 0x06
 | ||||
| #define REG_SPIC_READ_STATUS 0x010C			//O 0x05
 | ||||
| #define REG_SPIC_CTRLR2 0x0110				//O 0x51
 | ||||
| #define REG_SPIC_FBAUDR 0x0114				//O 0x1
 | ||||
| #define REG_SPIC_ADDR_LENGTH 0x0118			//O 0x3
 | ||||
| #define REG_SPIC_AUTO_LENGTH 0x011C			//O 0x20030011/0x20030021
 | ||||
| #define REG_SPIC_VALID_CMD 0x0120			//O 0x202
 | ||||
| #define REG_SPIC_FLASE_SIZE 0x0124			//O 0x0E
 | ||||
| #define REG_SPIC_FLUSH_FIFO 0x0128			//O 0
 | ||||
| 
 | ||||
| VOID SpicInitRtl8195A(u8 InitBaudRate, u8 SpicBitMode);			// spi-flash controller initialization
 | ||||
| VOID SpicRxCmdRtl8195A(u8 cmd); 								// recieve command
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue