TelenkovDmitry hace 7 años
padre
commit
6bab4025a1
Se han modificado 70 ficheros con 7183 adiciones y 1992 borrados
  1. 1 1
      config/common_config.h
  2. 112 0
      docs/checklogfile.py
  3. BIN
      docs/checklogfile.pyc
  4. 2 53
      docs/test_log.py
  5. 1 1
      iap/User/main.c
  6. 23 6
      modules/Ethernet/private_mib.c
  7. 6 0
      modules/Ethernet/sntp.c
  8. 14 6
      modules/Ethernet/udp_netsetting.c
  9. BIN
      modules/HTTP_Server/fs/info.html
  10. BIN
      modules/HTTP_Server/fs/login.html
  11. BIN
      modules/HTTP_Server/fs/main.css
  12. BIN
      modules/HTTP_Server/fs/main.js
  13. BIN
      modules/HTTP_Server/fs/rslogin.html
  14. BIN
      modules/HTTP_Server/fs/settings.html
  15. BIN
      modules/HTTP_Server/fs/ups_history.html
  16. 746 774
      modules/HTTP_Server/fsdata.c
  17. 207 842
      modules/HTTP_Server/http_server.c
  18. 3 3
      modules/HTTP_Server/web_params_api.c
  19. 10 0
      modules/Makefile
  20. 1 1
      modules/common/hal.c
  21. 11 5
      modules/log/log.c
  22. 2 0
      modules/log/log.h
  23. 32 4
      modules/log/ringfs.c
  24. 4 4
      modules/monitor/ups_monitor.c
  25. 4 2
      modules/parameters.c
  26. 326 0
      modules/radius/radius_user.c
  27. 59 0
      modules/radius/radius_user.h
  28. 27 14
      modules/settings_api.c
  29. 2 0
      modules/settings_api.h
  30. 1 0
      modules/sys_api.c
  31. 7 5
      modules/testing/testing.c
  32. 12 0
      peripheral_modules/src/usart.c
  33. 46 0
      projects/iar/bt-670x.ewp
  34. 3 0
      service_hw/Settings/bt_6701_settings.c
  35. 2 2
      service_hw/buttons/buttons.c
  36. 564 0
      thirdparty/FreeRadius/include/freeradius-client.h
  37. 189 0
      thirdparty/FreeRadius/include/includes.h
  38. 53 0
      thirdparty/FreeRadius/include/messages.h
  39. 28 0
      thirdparty/FreeRadius/include/pathnames.h
  40. 893 0
      thirdparty/FreeRadius/lib/avpair.c
  41. 178 0
      thirdparty/FreeRadius/lib/buildreq.c
  42. 943 0
      thirdparty/FreeRadius/lib/config.c
  43. 504 0
      thirdparty/FreeRadius/lib/dict.c
  44. 49 0
      thirdparty/FreeRadius/lib/fr_log.c
  45. 251 0
      thirdparty/FreeRadius/lib/fr_md5.c
  46. 86 0
      thirdparty/FreeRadius/lib/fr_md5.h
  47. 56 0
      thirdparty/FreeRadius/lib/fr_options.h
  48. 29 0
      thirdparty/FreeRadius/lib/rc-md5.c
  49. 28 0
      thirdparty/FreeRadius/lib/rc-md5.h
  50. 549 0
      thirdparty/FreeRadius/lib/sendserver.c
  51. 389 0
      thirdparty/FreeRadius/lib/util.c
  52. 50 0
      thirdparty/FreeRadius/lib/util.h
  53. 103 0
      thirdparty/FreeRadius/radius_config.h
  54. 20 10
      user/init_task.c
  55. 4 1
      user/main.c
  56. 4 4
      user/main.h
  57. 1 0
      web_interface/Gruntfile.js
  58. BIN
      web_interface/error.html
  59. BIN
      web_interface/index.html
  60. BIN
      web_interface/login.html
  61. 1 1
      web_interface/src/wui/info.html
  62. 2 2
      web_interface/src/wui/login.html
  63. 487 232
      web_interface/src/wui/main.css
  64. 1 1
      web_interface/src/wui/main.js
  65. 35 0
      web_interface/src/wui/rslogin.html
  66. 21 17
      web_interface/src/wui/settings.html
  67. 1 1
      web_interface/src/wui/ups_history.html
  68. BIN
      web_interface/success.html
  69. BIN
      web_interface/upload.css
  70. BIN
      web_interface/upload.js

+ 1 - 1
config/common_config.h

@@ -62,7 +62,7 @@
 /**
   * @brief  Таймаут возврата в основное ПО, сек.
   */
-#define UPDATE_TIMEOUT  60
+#define UPDATE_TIMEOUT  10*60
 
 #define USER_FLASH_FIRST_PAGE_ADDRESS 0x08020000 /* Only as example see comment */
 #define USER_FLASH_LAST_PAGE_ADDRESS  0x08060000

+ 112 - 0
docs/checklogfile.py

@@ -0,0 +1,112 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-  
+import time, sys, getopt, os, random
+
+ip = ""
+login = "admin"
+password = "12345"
+
+def usage():
+    print "Usage:\r\n\
+        checklogfile.py <filename> - to check local log file\r\n\
+        checklogfile.py -d <ip-address> - to download and check log file"
+
+
+def parse(path):
+    f = open(path)
+    lines = [line.rstrip('\n') for line in f]
+ 
+    #Remove UTF8 BOM 
+    lines[0] = lines[0].replace('\xEF\xBB\xBF','')
+
+    #Remove empty lines
+    for i in range(len(lines)-1, len(lines)-10, -1):
+        #print "str -", i, lines[-i] 
+        if lines[i] == " "*118+"\x0D":
+            del lines[i]
+
+    print "len: ", len(lines)
+    return lines
+
+
+def do_login():
+        os.system("curl -s -b /tmp/cookies.txt -c /tmp/cookies.txt -d \"login=%s&password=%s\" http://%s/login.cgi > /dev/null" % (login, password, ip))
+
+
+def log_download(path):
+        print "Downloading log file..."
+	if 0 == os.system("curl -b /tmp/cookies.txt -c /tmp/cookies.txt \"http://%s/history.cgi?page=all&_=%s\" --output %s --progress" % (ip, random.randint(0, 0xFFFF), path)):
+            return True
+        else:
+            return False
+
+
+def check(path):
+    lines = parse(path)
+ 
+    lastptr = 0
+    for i in range(len(lines)):
+        #i = lines.index(s)
+        s = lines[i]
+        print "\rProcessing: %d%%" %( (i+1)*100/len(lines)),
+
+        #Check if string in valid format
+        if len(s) > 119 or s[0] != '"' or s.count('"') != 2 or s.count('\x00') != 0:
+            print "\nError. Log file is corrupted:"
+            print "Wrong string (at index %d) : %s" %(i+1, s)
+            return False
+
+        strdate = s.replace('"','').split(";")[3].rstrip()
+        #print strdate
+        newdate = time.strptime(strdate, "%d.%m.%y %H:%M:%S")
+        if i != 0:
+            if newdate < lastdate:
+                if lastptr == 0:
+                    lastptr = i+1
+                else:
+                    print "\nError. Wrong message order!"
+                    print "Look at index:", i+1 
+ 
+        lastdate = newdate        
+   
+    print "\nLast message index:", lastptr
+    print "Log file is OK"
+    return True
+
+        
+def main():
+    global ip
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "hd:", \
+                ["help", "download="])
+    except getopt.GetoptError:
+        usage()
+        sys.exit(2)
+    
+    for opt, arg in opts:
+        if opt in ("-h", "--help"):
+                usage()
+                sys.exit()
+        if opt in ("-d", "--download"):
+                ip = arg
+
+    if ip == "" and len(sys.argv) < 2:
+        usage()
+        sys.exit(2)
+
+    if ip == "": 
+        path = sys.argv[-1]
+    else:
+        path = "/tmp/checklog.csv"
+        do_login()
+        if not log_download(path):
+            print "Download error"
+            sys.exit(2)
+    
+    check(path)
+
+
+if __name__ == "__main__":
+    main()
+

BIN
docs/checklogfile.pyc


+ 2 - 53
docs/test_log.py

@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-  
 import os, random, sys, time, json, getopt, threading
 
-sys.path.append('../epu_tester')
+sys.path.append('../../stm32_prs/stm32_prs/branches/epu_tester')
 import extdevices
 import checklogfile
 
@@ -170,58 +170,7 @@ def on_off_test():
 		print "ON"
 		time.sleep(4)
 
-                #Waiting LOG restore
-                delay = 0
-		res = 1
-		while res != 0:
-			res = os.system("tail ./trace.txt | grep -a \"Write page\" > /dev/null")
-			if res != 0:
-				print "Waiting restore: %d" % delay
-				delay+=5
-				time.sleep(5)
-			else:
-				time.sleep(12)
-            
-                do_login()
-
-                #Get start timestamp
-                if timestamp == '':
-                    strdate = log_get_string(1, 0).replace('"','').split(";")[3].rstrip()
-                    print "Started at:", strdate
-                    timestamp = time.strptime(strdate, "%d.%m.%y %H:%M:%S")
-                
-                #Check if Log index was overfloved since test start. If so, finish the test.
-                lastpage = log_get_pagesnum()
-                if lastpage > 3000:
-                    lastpages = 3000
-                strdate = log_get_string(lastpage, 0).replace('"','').split(";")[3].rstrip()
-                if timestamp < time.strptime(strdate, "%d.%m.%y %H:%M:%S"):
-                    print "Test finished. Checking LOG.."
-                    #Download and check log file
-                    PATH = "/tmp/testlog.csv"
-                    if log_download(PATH):
-                        res = checklogfile.check(PATH)
-
-                    break                   
-
-                #Validate LOG pages
-                if msg:
-                    print "Finding message:", msg
-                    for i in range(1, int(log_get_pagesnum())):
-                            parsed_page = json.loads(log_get_page(i))
-                            if len(parsed_page) != 10:
-                                    print "Error. Corrupted page:"
-                                    stop_spam_task()
-                                    for i in parsed_page:
-                                        print i 
-                                    return False
-                            if msg in parsed_page:
-                                    print "Found:", i 
-                                    break
-                            else:
-                                    print "Page: %d" % i
-            
-                msg = log_get_string(2, 0)
+           
                 time.sleep(random.randint(1, 4))		
 	    except KeyboardInterrupt:
 		sys.exit(0)

+ 1 - 1
iap/User/main.c

@@ -154,7 +154,7 @@ void main(void)
 //    SD_NVIC_Init();
   } else {
     IAPviaETH = true;
-    timer_AddFunction(500, &LED_Blinky_Green);
+    timer_AddFunction(500, &LED_Blinky_Red);
   }
   
   /* Check if valid stack address (RAM address) */

+ 23 - 6
modules/Ethernet/private_mib.c

@@ -16,6 +16,7 @@
 #include "megatec.h"
 
 #include "FreeRTOS.h"
+#include "task.h"
 
 #ifdef PRINTF_STDLIB
 #include <stdio.h>
@@ -491,13 +492,25 @@ static void signals_set_value (struct obj_def *od, u16_t len, void *value)
     case 2: /* RestoreSignal */
       val = *((s32_t*)value);
       if (val == 1) {
-        HTTP_ResetSettings();
+    	SNMP_SendUserTrap(DEVICE_RESTORED);
+		log_event_data(LOG_SYSTEM_DEFCONFIG, "Администратор");
+		vTaskDelay(500);
+		SETTINGS_SetPartDefault();
+		SETTINGS_Save();
       }
     break;
     case 3: /* RebootSignal */
       val = *((s32_t*)value);
-      if (val == 1)
-        HTTP_StartResetTask(false);
+      if (val == 1){
+#ifndef BT6702_SERVICE
+		SNMP_SendUserTrap(DEVICE_REBOOTED);
+		log_event_data(LOG_SYSTEM_BOOT, "Администратор");
+
+		vTaskDelay(1010);
+		LOG_Disable();
+#endif
+		NVIC_SystemReset();
+      }
     break;
 	case 5: /* DO1 */
 	  if(sSettings.sInOuts.ro_type_source[0] == SNMP_SET){
@@ -528,7 +541,7 @@ static void signals_set_value (struct obj_def *od, u16_t len, void *value)
 	  if(val == 0){
 		  res = ups_metac_service_pdu(ups_cancel_test);
 		  if(res == 1){
-			  log_event_data(LOG_TEST_UPS, "Администратор(Останов)");
+			  log_event_data(LOG_TEST_UPS, "Администратор (Останов)");
 		  }
 	  }
 	  else if(val > 0 && val < 100){
@@ -556,8 +569,9 @@ static void signals_set_value (struct obj_def *od, u16_t len, void *value)
 	  float shtdn_val = atof(val_string);
 	  if(shtdn_val == 0){
 		  res = ups_metac_service_pdu(ups_cancel_shut_down);
-		 	if(res == 1)
-		 		log_event_data(LOG_SHUTDOWN_UPS, "Администратор(Останов)");
+		 	if(res == 1){
+		 		log_event_data(LOG_SHUTDOWN_UPS, "Администратор (Останов)");
+		 	}
 	  }
 	  else{
 		TimeParamFloat = shtdn_val;
@@ -610,6 +624,7 @@ static u8_t signals_set_test (struct obj_def *od, u16_t len, void *value)
 		if ( len <= 1 )
 	    {
 		   val_string = (char*)value;
+		   val_string[len] = 0;
 		   if(atoi(val_string) <= 1){
 			   if(sSettings.sInOuts.ro_type_source[0] == SNMP_SET)
 				   set_ok = 1;
@@ -620,6 +635,7 @@ static u8_t signals_set_test (struct obj_def *od, u16_t len, void *value)
 		if ( len <= 1 )
 		{
 		   val_string = (char*)value;
+		   val_string[len] = 0;
 		   if(atoi(val_string) <= 1){
 			   if(sSettings.sInOuts.ro_type_source[1] == SNMP_SET)
 				   set_ok = 1;
@@ -636,6 +652,7 @@ static u8_t signals_set_test (struct obj_def *od, u16_t len, void *value)
 		if ( len <= 3 )
 		{
 		   val_string = (char*)value;
+		   val_string[len] = 0;
 		   if(atof(val_string) <= 10){
 			set_ok = 1;
 		   }

+ 6 - 0
modules/Ethernet/sntp.c

@@ -5,6 +5,8 @@
 #include <string.h>
 #include <time.h>
 
+#include "semphr.h"
+
 #ifdef PRINTF_STDLIB
 #include <stdio.h>
 #endif
@@ -46,6 +48,8 @@ static int port = 123;
   */
 extern SETTINGS_t sSettings;
 
+extern SemaphoreHandle_t flash_mutex;
+
 /**
   * @brief  Разовая синхронизация времени при старте контроллера
   */
@@ -166,11 +170,13 @@ static void recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
 	/* Сохраним время последней синхронизации */
 	TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
 		
+	xSemaphoreTake(flash_mutex, portMAX_DELAY);
 	memset(sSettings.sSNTP.data, 0, sizeof(sSettings.sSNTP.data));
 	
 	sprintf(sSettings.sSNTP.data, "%02d.%02d.%02d %02d:%02d:%02d", 
 			data.date, data.month, data.year,
 			data.hours, data.minutes, data.seconds);
+	xSemaphoreGive(flash_mutex);
 	
     timeout = VALID_TIMEOUT;
     

+ 14 - 6
modules/Ethernet/udp_netsetting.c

@@ -140,17 +140,24 @@ void udp_recieve_parser(char *buf, u16_t rcvlen)
   const uint8_t len = 100;
   char value[100];
   char str[100];
+  char work_buf[DATA_BUF_LEN1];
 
   memset(str, 0, 100);
 
- // ClearParamString(buf);
+  memset(work_buf, 0, DATA_BUF_LEN1);
+
+  //ClearParamString(buf);
 
   memset(value, 0, len);
   memset(str, 0, len);
+  if(rcvlen < (DATA_BUF_LEN1 - 1))
+	  strncpy(work_buf, buf, rcvlen);
+  else
+	  strncpy(work_buf, buf, (DATA_BUF_LEN1 - 1));
 
   DBG buf[rcvlen]='\0';
   DBG printf("Rcvd (%d bytes): \t%s\r\n", rcvlen, buf);
-  GetUDPParamValue(buf, "\"serno\"", value, &valueLen);
+  GetUDPParamValue(work_buf, "\"serno\"", value, &valueLen);
   if(valueLen != 0)
 	  GetSerialNumberStr(str, &len2);
   else
@@ -160,11 +167,11 @@ void udp_recieve_parser(char *buf, u16_t rcvlen)
   {
 	  memset(str, 0, len);
 
-	  GetUDPParamValue(buf, "\"dhcp\"", str, &valueLen);
+	  GetUDPParamValue(work_buf, "\"dhcp\"", str, &valueLen);
 
 	 // memset(str, 0, len);
 	  memset(value, 0, len);
-	  GetUDPParamValue(buf, "\"ipaddress\"", value, &valueLen);
+	  GetUDPParamValue(work_buf, "\"ipaddress\"", value, &valueLen);
 	  if(valueLen != 0)
 	  {
 		  SetUDPDhcpStateStr(str);
@@ -179,12 +186,12 @@ void udp_recieve_parser(char *buf, u16_t rcvlen)
 	  {
 		  memset(value, 0, len);
 
-		  GetUDPParamValue(buf, "\"gateway\"", value, &valueLen);
+		  GetUDPParamValue(work_buf, "\"gateway\"", value, &valueLen);
 		  if(valueLen != 0)
 			  SetGatewayStr(value);
 		  memset(value, 0, len);
 
-		  GetUDPParamValue(buf, "\"mask\"", value, &valueLen);
+		  GetUDPParamValue(work_buf, "\"mask\"", value, &valueLen);
 		  if(valueLen != 0)
 			  SetMaskStr(value);
 		  memset(value, 0, len);
@@ -223,6 +230,7 @@ bool http_server_serve(struct netconn *conn)
     if (res == ERR_OK)
     {
         netbuf_data(inbuf, (void**)&buf, &buflen);
+        //buf[buflen] = 0;
         udp_recieve_parser(buf, buflen);
         flag = true;
         netbuf_delete(inbuf);

BIN
modules/HTTP_Server/fs/info.html


BIN
modules/HTTP_Server/fs/login.html


BIN
modules/HTTP_Server/fs/main.css


BIN
modules/HTTP_Server/fs/main.js


BIN
modules/HTTP_Server/fs/rslogin.html


BIN
modules/HTTP_Server/fs/settings.html


BIN
modules/HTTP_Server/fs/ups_history.html


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 746 - 774
modules/HTTP_Server/fsdata.c


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 207 - 842
modules/HTTP_Server/http_server.c


+ 3 - 3
modules/HTTP_Server/web_params_api.c

@@ -423,7 +423,7 @@ void HTTP_ResetSettings(void)
   //taskENTER_CRITICAL();
 
   SNMP_SendUserTrap(DEVICE_RESTORED);
-  log_event_data(LOG_SYSTEM_DEFCONFIG, "Администратор");
+  log_event_data(LOG_SYSTEM_DEFCONFIG, name_login);
   vTaskDelay(500);
   SETTINGS_SetPartDefault();
   SETTINGS_Save();
@@ -440,7 +440,7 @@ void HTTP_SaveSettings(void)
   
   SETTINGS_Save();
   
-  log_event_data(LOG_SETTING_SAVE, "Администратор");
+  log_event_data(LOG_SETTING_SAVE, name_login);
 
 //  taskEXIT_CRITICAL();
 
@@ -486,7 +486,7 @@ void vTaskReboot(void * pvParameters)
 	if (mode)
 	{
 	  SNMP_SendUserTrap(FW_VERSION_UPDATE);
-	  log_event_data(LOG_UPDATE_SOFT, "Администратор");
+	  log_event_data(LOG_UPDATE_SOFT, name_login);
 	  SetLoadMode();
 	  HTTP_SaveSettings();
       vTaskDelay(2000);

+ 10 - 0
modules/Makefile

@@ -45,6 +45,7 @@ INCLUDES += -Icommon
 INCLUDES += -Imonitor
 INCLUDES += -Ilog
 INCLUDES += -Itesting
+INCLUDES += -Iradius
 CSRC += $(wildcard leds/*.c)
 CSRC += $(wildcard buttons/*.c)
 CSRC += $(wildcard jumper/*.c)
@@ -54,6 +55,7 @@ CSRC += $(wildcard common/*.c)
 CSRC += $(wildcard monitor/*.c)
 CSRC += $(wildcard log/*.c)
 CSRC += $(wildcard testing/*.c)
+CSRC += $(wildcard radius/*.c)
 
 CFLAGS += -DOS_FREERTOS
 CFLAGS += -DHARDWARE_$(shell echo $(HARDWARE) | tr a-z A-Z)
@@ -104,6 +106,14 @@ INCLUDES += -I../thirdparty/PolarSSL/include/polarssl/
 INCLUDES += -I../thirdparty/PolarSSL/include/
 
 CSRC += $(wildcard ../thirdparty/PolarSSL/library/*.c)
+
+#RADDIUS_SERVER
+
+INCLUDES += -I../thirdparty/FreeRadius/
+INCLUDES += -I../thirdparty/FreeRadius/include/
+INCLUDES += -I../thirdparty/FreeRadius/lib/
+
+CSRC += $(wildcard ../thirdparty/FreeRadius/lib/*.c)
     
     
 CFLAGS += -DUSE_STDPERIPH_DRIVER -DSTM32F40_41xxx -DLOG_ENABLE

+ 1 - 1
modules/common/hal.c

@@ -19,7 +19,7 @@
 void Reboot(void) {
 #ifndef BT6702_SERVICE
 	SNMP_SendUserTrap(DEVICE_REBOOTED);
-	log_event_data(LOG_SYSTEM_BOOT, "Администратор");
+	log_event_data(LOG_SYSTEM_BOOT, name_login);
 
 	vTaskDelay(1010);
 	LOG_Disable();

+ 11 - 5
modules/log/log.c

@@ -11,6 +11,8 @@
 
 char logFileBuf[FILE_BUF_MAX_LEN];
 
+char name_login[50];
+
 const char* logsStrShortRu[] =
 {
 	"Перезагрузка контроллера",
@@ -112,7 +114,7 @@ void log_task(void* params)
 	for(;;){
 		flUpdateLog = true;
 		vTaskDelay(LOG_TIME);
-	/*	vTaskDelay(50);
+		/*vTaskDelay(50);
 		log_event_data(LOG_SYSTEM_BOOT, "Администратор");
 		log_add(")215.7;215.7;220.5;000;50.1;2.30;25.0;00000001;");*/
 	}
@@ -127,16 +129,20 @@ void log_init(bool format) {
 	ringfs_flash.sector_count = spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET;
 
 	ringfs_init(&fs, &ringfs_flash, LOG_ENTRY_VERSION, sizeof(log_entry_t));
-	if (format || ringfs_scan(&fs) != 0)
+	if (format || ringfs_scan(&fs) != 0){
+		DBG printf("FAT1 false\r\n");
 		ringfs_format(&fs);
-
+	}
+	DBG printf("FAT1 true\r\n");
 	ringfs_flash2.sector_size = spi_flash_desc.sector_size;
 	ringfs_flash2.sector_count = spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET;
 
 	ringfs_init(&fs2, &ringfs_flash2, LOG_ENTRY_VERSION, sizeof(log_entry_t));
-	if (format || ringfs_scan(&fs2) != 0)
+	if (format || ringfs_scan(&fs2) != 0){
+		DBG printf("FAT2 false\r\n");
 		ringfs_format(&fs2);
-
+	}
+	DBG printf("FAT2 true\r\n");
 	fLogInit = true;
 
 	log_mutex = xSemaphoreCreateMutex();

+ 2 - 0
modules/log/log.h

@@ -10,6 +10,8 @@
 
 extern char logFileBuf[FILE_BUF_MAX_LEN];
 
+extern char name_login[50];
+
 typedef __packed enum {
 	LOG_SYSTEM_BOOT = 0x00,			// device booted
 	LOG_SYSTEM_DEFCONFIG,	// default config applied

+ 32 - 4
modules/log/ringfs.c

@@ -191,6 +191,8 @@ int ringfs_scan(struct ringfs *fs)
     /* If there's no IN_USE sector, we start at the first one. */
     bool used_seen = false;
 
+    bool err_sector = true;
+
     /* Iterate over sectors. */
     for (int sector=0; sector<fs->flash->sector_count; sector++) {
         int addr = _sector_address(fs, sector);
@@ -202,7 +204,15 @@ int ringfs_scan(struct ringfs *fs)
         /* Detect partially-formatted partitions. */
         if (header.status == SECTOR_FORMATTING) {
         	DBG printf("ringfs_scan: partially formatted partition\r\n");
-            return -1;
+        	if(err_sector){
+				err_sector = false;
+				_sector_free(fs, addr);
+				//fs->flash->read(fs->flash, addr, &header, sizeof(header));
+				header.status = SECTOR_FREE;
+				header.version = fs->version;
+			}else{
+				return -1;
+			}
         }
 
         /* Detect and fix partially erased sectors. */
@@ -214,14 +224,32 @@ int ringfs_scan(struct ringfs *fs)
         /* Detect corrupted sectors. */
         if (header.status != SECTOR_FREE && header.status != SECTOR_IN_USE) {
         	DBG printf("ringfs_scan: corrupted sector %d\r\n", sector);
-            return -1;
+        	if(err_sector){
+				err_sector = false;
+				_sector_free(fs, addr);
+				//fs->flash->read(fs->flash, addr, &header, sizeof(header));
+				header.status = SECTOR_FREE;
+				header.version = fs->version;
+			}else{
+				return -1;
+			}
         }
 
         /* Detect obsolete versions. We can't do this earlier because the version
          * could have been invalid due to a partial erase. */
         if (header.version != fs->version) {
-            DBG printf("ringfs_scan: incompatible version 0x%08"PRIx32"\r\n", header.version);
-            return -1;
+        	DBG printf("ringfs_scan: corrupted sector %d\r\n", sector);
+        	DBG printf("ringfs_scan: incompatible version 0x%08"PRIx32"\r\n", header.version);
+            if(err_sector){
+            	err_sector = false;
+            	_sector_free(fs, addr);
+            	//fs->flash->read(fs->flash, addr, &header, sizeof(header));
+            	DBG printf("ringfs_scan: incompatible version 0x%08"PRIx32"\r\n", header.version);
+            	header.status = SECTOR_FREE;
+            	header.version = fs->version;
+            }else{
+            	return -1;
+            }
         }
 
         /* Record the presence of a FREE sector. */

+ 4 - 4
modules/monitor/ups_monitor.c

@@ -97,8 +97,8 @@ void UPS_DI0Monitor(void)
 	  return;
 	}
 
-	if (DI0StateCurrent)
-	  flCriticalAlarm = true;
+	/*if (DI0StateCurrent)
+	  flCriticalAlarm = true;*/
 
 	// Значение параметра изменилось
 	if (DI0StateCurrent != DI0OldState)
@@ -164,9 +164,9 @@ void UPS_CriticalAlarmMonitor(void)
 
   if(CriticalAlarmCurrent){
 	  if (UPS.Present)
-		  LED_Toggle(LED_MAJOR_R);
-	  else
 		  LED_On(LED_MAJOR_R);
+	  else
+		  LED_Toggle(LED_MAJOR_R);
   }
   else{
 	  LED_Off(LED_MAJOR_R);

+ 4 - 2
modules/parameters.c

@@ -980,7 +980,7 @@ void SetTimeStr(char *str)
 
 // ************************************************************************** //
 //                             Параметры SNTP
-
+#ifndef BT6702_SERVICE
 /**
   * @brief  Состояние SNTP
   */
@@ -990,7 +990,8 @@ void SetSntpStateStr(char *str)
   if (strncmp(str, "1", 1) == 0){
 	sSettings.sSNTP.sntpEnable = true;
 	if(old_sntpEnable != sSettings.sSNTP.sntpEnable){
-		SNTP_Enable(sSettings.sSNTP.sntpEnable);
+		SNTP_Init();
+		//vTaskDelay(7000);
 		SNTP_Poll();
 	}
   }
@@ -999,6 +1000,7 @@ void SetSntpStateStr(char *str)
 	SNTP_Enable(sSettings.sSNTP.sntpEnable);
   }
 }
+#endif
 
 /**
   * @brief  IP адрес SNTP сервера

+ 326 - 0
modules/radius/radius_user.c

@@ -0,0 +1,326 @@
+/********************************* (C) РОТЕК ***********************************
+ * @module  template
+ * @file    template.c
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   template
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+#include "stm32f4xx.h"  
+#include "radius_user.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "freeradius-client.h"
+#include "fr_options.h"
+
+rc_handle	rcHandle;
+
+int auth_order = AUTH_LOCAL_SND;
+int login_tries = 4;
+int login_timeout = 60;
+char* nologin = "?";
+char* issue = "?";
+char* authserver = "192.168.1.2:1645";
+char* acctserver = "0";
+char* servers = "?";
+char* dictionary = "?";
+char *login_radius = "?";
+char *mapfile = "?";
+char *default_realm = NULL;
+int radius_timeout = 10;
+int radius_retries = 3;
+int radius_deadtime = 0;
+char *bindaddr = "*";
+char *login_local = "?";
+
+OPTION      rcOptions[] = {
+{"auth_order",	 	OT_AUO, ST_UNDEF, (void*)&auth_order}, // AUTH_LOCAL_FST AUTH_RADIUS_FST AUTH_LOCAL_SND AUTH_RADIUS_SND
+{"login_tries",	 	OT_INT, ST_UNDEF, (void*)&login_tries},
+{"login_timeout",	OT_INT, ST_UNDEF, (void*)&login_timeout},
+{"nologin",		    OT_STR, ST_UNDEF, NULL},
+{"issue",		    OT_STR, ST_UNDEF, NULL},
+// RADIUS specific options 
+{"authserver",		OT_SRV, ST_UNDEF, (void*)&authserver},
+{"acctserver",		OT_SRV, ST_UNDEF, (void*)&acctserver},
+{"servers",		    OT_STR, ST_UNDEF, (void*)&servers},
+{"dictionary",		OT_STR, ST_UNDEF, (void*)&dictionary},
+{"login_radius",	OT_STR, ST_UNDEF, (void*)&login_radius},
+{"mapfile",		    OT_STR, ST_UNDEF, (void*)&mapfile},
+{"default_realm",	OT_STR, ST_UNDEF, (void*)&default_realm},
+{"radius_timeout",	OT_INT, ST_UNDEF, (void*)&radius_timeout},
+{"radius_retries",	OT_INT,	ST_UNDEF, (void*)&radius_retries},
+{"radius_deadtime",	OT_INT, ST_UNDEF, (void*)&radius_deadtime},
+{"bindaddr",		OT_STR, ST_UNDEF, (void*)&bindaddr},
+// local options 
+{"login_local",		OT_STR, ST_UNDEF, (void*)&login_local},
+};
+
+static DICT_ATTR   attr_1;
+static DICT_ATTR   attr_2;
+static DICT_ATTR   attr_3;
+
+static char rc_msg[PW_MAX_MSG_SIZE];
+
+
+RadiusClientResult RC_Login(char* login, char* pas)
+{
+    VALUE_PAIR* send;
+    VALUE_PAIR* received;
+    uint32_t	service;
+    
+    int result;
+    
+    memset(rc_msg, 0, PW_MAX_MSG_SIZE);
+
+    memset(&rcHandle, 0, sizeof(rc_handle));
+  
+    rc_read_config(&rcHandle);
+    
+    // Формирование атрибутов
+    // 1. User name
+    strncpy(attr_1.name, login, strlen(login));
+    attr_1.value = 1;
+    attr_1.type = PW_TYPE_STRING;
+    attr_1.next = NULL;
+    
+    // 2. Password
+    strncpy(attr_2.name, pas, strlen(pas));
+    attr_2.value = 2;
+    attr_2.type = PW_TYPE_STRING;
+    attr_2.next = &attr_1;
+    
+    // 3. Service type
+    strcpy(attr_3.name, "Service-Type");
+    attr_3.value = 6;
+    attr_3.type = PW_TYPE_INTEGER;
+    attr_3.next = &attr_2;
+    
+    rcHandle.dictionary_attributes = &attr_3;
+    
+    send = NULL;
+    
+	// User-Name
+    if (rc_avpair_add(&rcHandle, &send, PW_USER_NAME, login, -1, 0) == NULL)
+		return RC_ERROR;
+    
+	// User-Password
+	if (rc_avpair_add(&rcHandle, &send, PW_USER_PASSWORD, pas, -1, 0) == NULL)
+		return RC_ERROR;
+	
+	// Service-Type
+	service = PW_AUTHENTICATE_ONLY;
+	if (rc_avpair_add(&rcHandle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
+		return RC_ERROR;
+
+    result = rc_auth(&rcHandle, 0, send, &received, rc_msg);
+    
+    switch (result)
+    {
+    case USER_RC :
+        return RC_LOGIN_USER_OK;
+    break;
+    
+    case ADMIN_RC :
+        return RC_LOGIN_ADMIN_OK;
+    break;
+    
+    case NET_ERR_RC :
+        return RC_NET_ERR;
+    break;
+    
+    case ERROR_RC :
+        return RC_ERROR;
+    break;
+    
+    case BADRESP_RC :
+        return RC_ACC_DENIED;
+    break;
+    
+    case REJECT_RC :
+        return RC_ACC_DENIED;
+    break;
+    
+    default :
+        return RC_ERROR;
+    break;
+    }
+    return RC_ERROR;
+    //printf("\r\n");
+    //printf("Radius client result: %i\r\n", result);
+    
+}
+
+/**
+  * @brief  
+  */
+int RD_TestInit(void)
+{
+    int         result;
+	char		username[128];
+	char        passwd[AUTH_PASS_LEN + 1];
+	VALUE_PAIR 	*send, *received;
+	uint32_t	service;
+	char 		msg[PW_MAX_MSG_SIZE], username_realm[256];
+	char		*default_realm;
+	  
+    // Моя подготовка 
+    memset(username, 0, 128);
+    memset(passwd, 0, AUTH_PASS_LEN + 1);
+    memset(msg, 0, PW_MAX_MSG_SIZE);
+    memset(username_realm, 0, 256);
+    
+    
+    // Просто копируем структуру настроек которая жесто задана
+    rc_read_config(&rcHandle);
+   
+    // Словарь пока опускаем и не инициализируем
+    //if (rc_read_dictionary(&rcHandle, rc_conf_str(&rcHandle, "dictionary")) != 0)
+	//	return ERROR_RC;
+  
+    // Заполняем словарь
+    // 1. User name
+    strcpy(attr_1.name, "test1");
+    attr_1.value = 1;
+    attr_1.type = PW_TYPE_STRING;
+    attr_1.next = NULL;
+    
+    // 2. Password
+    strcpy(attr_2.name, "12345");
+    attr_2.value = 2;
+    attr_2.type = PW_TYPE_STRING;
+    attr_2.next = &attr_1;
+    
+    // 3. Service type
+    strcpy(attr_3.name, "Service-Type");
+    attr_3.value = 6;
+    attr_3.type = PW_TYPE_INTEGER;
+    attr_3.next = &attr_2;
+    
+/*    
+    attr_3.value = 244;
+    attr_3.type = PW_TYPE_STRING;
+    attr_3.next = &attr_2;
+*/    
+    rcHandle.dictionary_attributes = &attr_3;
+    
+    // Не понял что за параметра, пока NULL
+    //default_realm = rc_conf_str(rh, "default_realm");
+    default_realm = NULL;
+
+    // Рараметры ожидаются от пользователя
+    //strncpy(username, "dtelenkov", 9);
+    strncpy(username, "test1", 5);
+    strncpy(passwd, "12345", 5);
+    //strncpy(username, rc_getstr (rh, "login: ",1), sizeof(username));
+	//strncpy (passwd, rc_getstr(rh, "Password: ",0), sizeof (passwd));
+    
+    send = NULL;
+        
+    /*
+	 * Fill in User-Name
+	 */
+
+	strncpy(username_realm, username, sizeof(username_realm));
+
+	/* Append default realm */
+    /*
+	if ((strchr(username_realm, '@') == NULL) && default_realm &&
+	    (*default_realm != '\0'))
+	{
+		strncat(username_realm, "@", sizeof(username_realm)-strlen(username_realm)-1);
+		strncat(username_realm, default_realm, sizeof(username_realm)-strlen(username_realm)-1);
+	}
+    */
+    
+	if (rc_avpair_add(&rcHandle, &send, PW_USER_NAME, username_realm, -1, 0) == NULL)
+		return ERROR_RC;
+    
+	/*
+	 * Fill in User-Password
+	 */
+	if (rc_avpair_add(&rcHandle, &send, PW_USER_PASSWORD, passwd, -1, 0) == NULL)
+		return ERROR_RC;
+
+	/*
+	 * Fill in Service-Type
+	 */
+	service = PW_AUTHENTICATE_ONLY;
+	if (rc_avpair_add(&rcHandle, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL)
+		return ERROR_RC;
+#if 0
+	result = rc_auth(&rcHandle, 0, send, &received, msg);
+
+	if (result == OK_RC)
+	{
+		fprintf(stderr, "\"%s\" RADIUS Authentication OK\n", username);
+	}
+	else
+	{
+		fprintf(stderr, "\"%s\" RADIUS Authentication failure (RC=%i)\n", username, result);
+	}
+
+	
+#endif
+	send = NULL;
+    
+    return 0;
+}
+
+void initFdsets(fdsets *sets)
+{
+    memset((sets)->buf1, 0xab, 8); 
+    memset((sets)->buf2, 0xab, 8); 
+    memset((sets)->buf3, 0xab, 8); 
+    memset((sets)->buf4, 0xab, 8); 
+}
+
+bool recvSelect(fdsets *sets, int *socket, uint32_t timeout)
+{
+    struct timeval tv;
+
+    tv.tv_sec = 0;
+    tv.tv_usec = timeout * 1000;
+      
+    FD_ZERO(&(sets->readset));
+    FD_SET(*socket, &sets->readset);
+    FD_ZERO(&sets->errset);
+    FD_SET(*socket, &sets->errset);
+        
+    lwip_select(*socket + 1, &sets->readset, NULL, &sets->errset, &tv);
+        
+    if (FD_ISSET(*socket, &sets->readset)) 
+        return true;
+
+    return false;
+}
+
+//
+int RC_GetAccessRights(char* buf)
+{
+    uint16_t tmpLen = 0;
+    uint8_t att = 10;
+    
+    while (att)
+    {
+        att--;  // Предохранитель
+        
+        if (strstr(buf, "user") != 0) {
+            return USER_RC; }
+        else if (strstr(buf, "admin") != 0) {
+            return ADMIN_RC; }
+        
+        tmpLen = strlen(buf);
+        buf += tmpLen + 1;            
+    }
+    
+    return ERROR_RC;
+}
+
+
+/********************************* (C) РОТЕК **********************************/

+ 59 - 0
modules/radius/radius_user.h

@@ -0,0 +1,59 @@
+/******************************* (C) LiteMesh **********************************
+ * @module  template
+ * @file    template.h
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   template
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+/* Define to prevent recursive  ----------------------------------------------*/
+#ifndef __RADIUS_USER_H
+#define __RADIUS_USER_H
+
+#include "lwip/sockets.h"
+#include <stdbool.h>
+
+typedef enum
+{
+    RC_ERROR = 0,       // Внутренняя ошибка FreeRadius. 
+    RC_LOGIN_ADMIN_OK,  // Успешный логин под admin
+    RC_LOGIN_USER_OK,   // Успешный логин под user
+    RC_NET_ERR,         // Ошибка сетевого взаимодействия
+    RC_ACC_DENIED,      // Не удалось залогиниться, доступ закрыт
+    
+} RadiusClientResult;
+
+
+typedef struct 
+{
+    u8_t   buf1[8];
+    fd_set readset;
+    u8_t   buf2[8];
+    fd_set writeset;
+    u8_t   buf3[8];
+    fd_set errset;
+    u8_t   buf4[8];
+  
+} fdsets;
+
+RadiusClientResult RC_Login(char* login, char* pas);
+
+/**
+  * @brief  
+  */
+int RD_TestInit(void);
+
+
+void initFdsets(fdsets *sets);
+
+bool recvSelect(fdsets *sets, int *socket, uint32_t timeout);
+
+int RC_GetAccessRights(char* buf);
+
+#endif /* #ifndef __RADIUS_USER_H */
+
+/****************************** (C) LiteMesh ***************** end of file ****/

+ 27 - 14
modules/settings_api.c

@@ -22,6 +22,8 @@
 
 #include "FreeRTOS.h"
 #include "task.h"
+#include "semphr.h"
+#include "main.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -32,12 +34,15 @@
 #include "tinystdio.h"
 #endif
 
-#define DBG if(0)
+//#define DBG if(0)
 
 #if defined ( __ICCARM__ )
 #define DEVICE_MAC "00-00-00-00-00-03"
 #endif
 
+
+SemaphoreHandle_t flash_mutex;
+
 /**
   * @brief  Флаг подтверждения новых сетевых параметров пользователем
   */  
@@ -62,10 +67,10 @@ void SETTINGS_SetBootParamsDef(void)
   */
 void SETTINGS_SetWebParamsDef(void)
 {
-	  strcpy(sSettings.sWebParams.ip, "192.168.1.8");
-	  strcpy(sSettings.sWebParams.gate, "192.168.1.1");
+	  strcpy(sSettings.sWebParams.ip, "192.168.0.254");
+	  strcpy(sSettings.sWebParams.gate, "192.168.0.1");
 	  strcpy(sSettings.sWebParams.mask, "255.255.255.0");
-	  sSettings.sWebParams.dhcpEnable = 1;
+	  sSettings.sWebParams.dhcpEnable = 0;
 }
 
 /**
@@ -73,10 +78,10 @@ void SETTINGS_SetWebParamsDef(void)
   */
 void SETTINGS_SetTempWebParamsDef(void)
 {
-	  strcpy(sSettings.sWebTempParams.ip, "192.168.1.8");
-	  strcpy(sSettings.sWebTempParams.gate, "192.168.1.1");
+	  strcpy(sSettings.sWebTempParams.ip, "192.168.0.254");
+	  strcpy(sSettings.sWebTempParams.gate, "192.168.0.1");
 	  strcpy(sSettings.sWebTempParams.mask, "255.255.255.0");
-	  sSettings.sWebTempParams.dhcpEnable = 1;
+	  sSettings.sWebTempParams.dhcpEnable = 0;
 }
 
 /**
@@ -117,8 +122,9 @@ void SETTINGS_SetInfoDef(void)
 	  strcpy(sSettings.sInfo.productionData, "09.07.2017");
 	  strcpy(sSettings.sInfo.mac, DEVICE_MAC);
 	  strcpy(sSettings.sInfo.serialNumber, DEVICE_SERIAL);
-  }
+	  strcpy(sSettings.sFlags.testState, "T2OK");
 
+  }
   strcpy(sSettings.sInfo.comments, "");
 }  
 
@@ -144,13 +150,13 @@ void SETTINGS_SetServiceDef(void)
         case 0:
             sSettings.sAuth[user_id].level = ADMIN;
             strcpy(sSettings.sAuth[user_id].login, "admin");
-            strcpy(sSettings.sAuth[user_id].password, "12345");
+            strcpy(sSettings.sAuth[user_id].password, "R04ekR4MP2");
             break;
         case 1:
         default:
         	sSettings.sAuth[user_id].level = USER;
             strcpy(sSettings.sAuth[user_id].login, "user");
-            strcpy(sSettings.sAuth[user_id].password, "1234");
+            strcpy(sSettings.sAuth[user_id].password, "R03ekR4MP2");
             break;
         }
     }
@@ -184,11 +190,11 @@ void SETTINGS_SetINOUTSDef(void)
 void SETTINGS_SetRADIUSDef(void)
 {
   sSettings.sRADIUS.Auth_enable = true;
-  sSettings.sRADIUS.RDSEnable = true;
+  sSettings.sRADIUS.RDSEnable = false;
   strcpy(sSettings.sRADIUS.ServerIP, "0.0.0.0");
   sSettings.sRADIUS.port = 1812;
   sSettings.sRADIUS.key_access = 123;
-  strcpy(sSettings.sRADIUS.rds_password, "12345");
+  strcpy(sSettings.sRADIUS.rds_password, "R02ekR4MP2");
 }
   
 /**
@@ -218,7 +224,7 @@ void SETTINGS_SetPartDefault(void)
  // SETTINGS_SetServiceDef();
   SETTINGS_SetSntpDef();
   SETTINGS_SetINOUTSDef();
-  SETTINGS_SetRADIUSDef();
+ // SETTINGS_SetRADIUSDef();
   
   sSettings.CritSecCRC = SETTINGS_GetCritSecCRC();
 
@@ -272,10 +278,12 @@ void SETTINGS_SetDefaultDebug(void)
   */
 void SETTINGS_Save(void)
 {
+	xSemaphoreTake(flash_mutex, portMAX_DELAY);
   /* Calc critical section CRC and store to the settings structure */
   sSettings.CritSecCRC = SETTINGS_GetCritSecCRC();
 
   SETTINGS_WriteToFlash((uint8_t*)&sSettings, sizeof(sSettings));
+  xSemaphoreGive(flash_mutex);
 }
 
 /**
@@ -457,6 +465,7 @@ void SETTINGS_SetProDate(char *proDate, uint8_t len)
 
 	sSys = pvPortMalloc(sizeof(*sSys));
 	if (sSys) {
+	  SYS_Load(sSys);
 	  strcpy(sSys->proddate, proDate);
 	  SYS_Save(sSys);
 	  memset(sSettings.sInfo.productionData, 0, 40);
@@ -475,6 +484,7 @@ void SETTINGS_SetT2OK(void)
 
 	sSys = pvPortMalloc(sizeof(*sSys));
 	if (sSys) {
+	  SYS_Load(sSys);
 	  memset(sSettings.sFlags.testState, 0, 16);
 	  memcpy(sSettings.sFlags.testState, "T2OK", 4);
 	  strcpy(sSys->testState, sSettings.sFlags.testState);
@@ -492,5 +502,8 @@ void SETTINGS_SetDHCPOn(void)
   sSettings.sWebParams.dhcpEnable = 1;
 }
 
-
+void init_settings(void)
+{
+	  flash_mutex = xSemaphoreCreateMutex();
+}
 /********************************* (C) ROTEK **********************************/

+ 2 - 0
modules/settings_api.h

@@ -328,6 +328,8 @@ void SETTINGS_SetT2OK(void);
   */
 void SETTINGS_SetDHCPOn(void);
 
+void init_settings(void);
+
 #endif /* #ifndef SETTINGS_API_H */
 
 /********************************* (C) РОТЕК **********************************/

+ 1 - 0
modules/sys_api.c

@@ -84,6 +84,7 @@ bool SYS_SetDefault(SYS_t *settings) {
 
 	snprintf(settings->customer, CUST_LEN, SYS_CUSTOMER);
 	snprintf(settings->proddate, PROD_LEN, "00.00.00");
+	snprintf(settings->testState, 5, "T2OK");
 	settings->controlword = SETTINGS_CONTROL_WORD;
 
 	return true;

+ 7 - 5
modules/testing/testing.c

@@ -16,6 +16,7 @@
 #include "common_config.h"
 #include "stm32_uid.h"
 #include "led.h"
+#include "hal.h"
 
 #include "FreeRTOS.h"
 #include "task.h"
@@ -42,9 +43,8 @@ bool fServer = false;
 
 
 #define MSG_LEN   300
-char msg[MSG_LEN];
 
-uint8_t ID[33];
+char ID[33];
 
 extern SETTINGS_t   sSettings;       // Общая структура настроек
 
@@ -58,7 +58,7 @@ void vTaskTesting(void *params)
   for (;;)
   {
 	  //printf("Start testing task\r\n");
-  
+	  memset(ID, 0, 33);
 	  /* Читаем ID */
 	  GetSTM32IDStr(ID, &len);
 	  
@@ -77,6 +77,8 @@ void vTaskTesting(void *params)
 
         LED_Off(LED_INIT_R);
 	    fServer = false;
+	    vTaskDelay(2000);
+	    Reboot();
 	    vTaskDelete(NULL);
       }
       
@@ -92,8 +94,8 @@ void TEST_SendData(void)
   struct netconn *conn;
   struct netbuf *buf;
   char *data;
+  char msg[MSG_LEN];
   err_t err;
-  char str[20] = {0};
    
   /* Отправляем сообщение на сервер по UDP */
   memset(msg, 0, MSG_LEN);
@@ -122,7 +124,7 @@ void TEST_SendData(void)
 	  strcat(msg, VERSION);
 	  strcat(msg, ";;;");
       
-	  for (uint8_t i = 0; i < 12; i++) 
+	//  for (uint8_t i = 0; i < 12; i++)
 	  {
 		 strcat(msg, ID);
 	  }	

+ 12 - 0
peripheral_modules/src/usart.c

@@ -26,6 +26,18 @@
 #include "tinystdio.h"
 #endif
 
+#ifdef __ICCARM__
+  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)    
+
+
+PUTCHAR_PROTOTYPE   
+{   
+  USART_SendData(USER_USART, (u8) ch);   
+  while(USART_GetFlagStatus(USER_USART, USART_FLAG_TXE) == RESET) {}   
+  return ch;   
+}   
+#endif
+
 #ifdef BT6702_SERVICE
 #define UPS_RBUF_SIZE 1024
 #else

+ 46 - 0
projects/iar/bt-670x.ewp

@@ -336,6 +336,7 @@
           <state>$PROJ_DIR$\..\..\modules\STM32F4x7_ETH_Driver</state>
           <state>$PROJ_DIR$\..\..\modules\log</state>
           <state>$PROJ_DIR$\..\..\modules\testing</state>
+          <state>$PROJ_DIR$\..\..\modules\radius</state>
           <state>$PROJ_DIR$\..\..\thirdparty\FreeRTOS\include</state>
           <state>$PROJ_DIR$\..\..\thirdparty\FreeRTOS\portable\IAR\ARM_CM4F</state>
           <state>$PROJ_DIR$\..\..\thirdparty\lwip\src\include</state>
@@ -346,6 +347,9 @@
           <state>$PROJ_DIR$\..\..\thirdparty\lwip\arch</state>
           <state>$PROJ_DIR$\..\..\thirdparty\PolarSSL\include\polarssl</state>
           <state>$PROJ_DIR$\..\..\thirdparty\PolarSSL\include</state>
+          <state>$PROJ_DIR$\..\..\thirdparty\FreeRadius</state>
+          <state>$PROJ_DIR$\..\..\thirdparty\FreeRadius\include</state>
+          <state>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib</state>
         </option>
         <option>
           <name>CCStdIncCheck</name>
@@ -2056,6 +2060,12 @@
         <name>$PROJ_DIR$\..\..\modules\monitor\ups_monitor.c</name>
       </file>
     </group>
+    <group>
+      <name>radius</name>
+      <file>
+        <name>$PROJ_DIR$\..\..\modules\radius\radius_user.c</name>
+      </file>
+    </group>
     <group>
       <name>STM32F4x7_ETH_Driver</name>
       <file>
@@ -2224,6 +2234,42 @@
   </group>
   <group>
     <name>thirdparty</name>
+    <group>
+      <name>freeradius</name>
+      <group>
+        <name>lib</name>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\avpair.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\buildreq.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\config.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\dict.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\fr_log.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\fr_md5.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\fr_options.h</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\rc-md5.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\sendserver.c</name>
+        </file>
+        <file>
+          <name>$PROJ_DIR$\..\..\thirdparty\FreeRadius\lib\util.c</name>
+        </file>
+      </group>
+    </group>
     <group>
       <name>freertos</name>
       <group>

+ 3 - 0
service_hw/Settings/bt_6701_settings.c

@@ -43,6 +43,7 @@ void SETTINGS_SetTest(char *state)
 
 	sSys = pvPortMalloc(sizeof(*sSys));
 	if (sSys) {
+	  SYS_Load(sSys);
 	  strcpy(sSys->testState, state);
 	  SYS_Save(sSys);
 	  vPortFree(sSys);
@@ -59,6 +60,7 @@ void SETTINGS_SetSerno(char *serno)
 
 	sSys = pvPortMalloc(sizeof(*sSys));
 	if (sSys) {
+	  SYS_Load(sSys);
 	  strcpy(sSys->serial, serno);
 	  strcpy(sSettings.sInfo.serialNumber, sSys->serial);
 	  SYS_Save(sSys);
@@ -76,6 +78,7 @@ void SETTINGS_SetMac(char *mac)
 
 	sSys = pvPortMalloc(sizeof(*sSys));
 	if (sSys) {
+	  SYS_Load(sSys);
 	  strcpy(sSys->mac, mac);
 	  strcpy(sSettings.sInfo.mac, sSys->mac);
 	  SYS_Save(sSys);

+ 2 - 2
service_hw/buttons/buttons.c

@@ -180,9 +180,9 @@ void BUTTON_DEF_UpHandler(void)
   */
 void BUTTON_DEF_DownHandler(void)
 {
-/*	LED_On(LED_INIT_R);
+	LED_On(LED_INIT_R);
 	LED_On(LED_MAJOR_R);
-	LED_On(LED_MINOR_R);*/
+	LED_On(LED_MINOR_R);
 
     fDefPressed = true;
 }

+ 564 - 0
thirdparty/FreeRadius/include/freeradius-client.h

@@ -0,0 +1,564 @@
+/*
+ * $Id: freeradius-client.h,v 1.18 2010/06/15 09:22:51 aland Exp $
+ *
+ * Copyright (C) 1995,1996,1997,1998 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#ifndef FREERADIUS_CLIENT_H
+#define FREERADIUS_CLIENT_H
+
+//#define CP_DEBUG
+
+#ifdef CP_DEBUG
+#define		DEBUG(args, ...)	rc_log(## args)
+#else
+#define		DEBUG(args, ...)	;
+#endif
+
+//#include	<sys/types.h>
+#include "radius_config.h"
+/*
+ * Include for C99 uintX_t defines is stdint.h on most systems.  Solaris uses
+ * inttypes.h instead.  Comment out the stdint include if you get an error,
+ * and uncomment the inttypes.h include.
+ */
+#include	<stdint.h>
+/* #include	<inttypes.h> */
+#ifdef PRINTF_STDLIB
+#include <stdio.h>
+#endif
+#ifdef PRINTF_CUSTOM
+#include "tinystdio.h"
+#endif
+#include	<time.h>
+
+
+/* for struct addrinfo and sockaddr_storage */
+//#include <sys/socket.h>
+#include <netdb.h>
+
+#undef __BEGIN_DECLS
+#undef __END_DECLS
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+#else
+# define __BEGIN_DECLS /* empty */
+# define __END_DECLS /* empty */
+#endif
+
+#define AUTH_VECTOR_LEN		16
+#define AUTH_PASS_LEN		(3 * 16) /* multiple of 16 */
+#define AUTH_ID_LEN		    64
+#define AUTH_STRING_LEN		253	 /* maximum of 253 */
+
+#define BUFFER_LEN		    8192
+
+#define NAME_LENGTH		    32
+#define GETSTR_LENGTH		128	//!< must be bigger than AUTH_PASS_LEN.
+
+#define MAX_SECRET_LENGTH	(3 * 16) /* MUST be multiple of 16 */
+
+#define VENDOR(x)		(((x) >> 16) & 0xffff)
+#define ATTRID(x)		((x) & 0xffff)
+
+#define PW_MAX_MSG_SIZE		256//4096
+
+   
+/* codes for radius_buildreq, radius_getport, etc. */
+#define AUTH			0
+#define ACCT			1
+
+/* defines for config.c */
+
+#define SERVER_MAX 8
+
+#define AUTH_LOCAL_FST	(1<<0)
+#define AUTH_RADIUS_FST	(1<<1)
+#define AUTH_LOCAL_SND	(1<<2)
+#define AUTH_RADIUS_SND	(1<<3)
+
+typedef struct server {
+	int max;
+	char *name[SERVER_MAX];
+	uint16_t port[SERVER_MAX];
+	char *secret[SERVER_MAX];
+	double deadtime_ends[SERVER_MAX];
+} SERVER;
+
+typedef struct pw_auth_hdr
+{
+	uint8_t		code;
+	uint8_t		id;
+	uint16_t	length;
+	uint8_t		vector[AUTH_VECTOR_LEN];
+	uint8_t		data[2];
+} AUTH_HDR;
+
+struct rc_conf
+{
+	struct _option		    *config_options;
+	struct sockaddr_storage	own_bind_addr;
+	unsigned		        own_bind_addr_set;
+
+	struct map2id_s		    *map2id_list;
+	struct dict_attr	    *dictionary_attributes;
+	struct dict_value	    *dictionary_values;
+	struct dict_vendor	    *dictionary_vendors;
+	char			        buf[GETSTR_LENGTH];
+    char    			    buf1[14];
+	char	    		    ifname[512];
+};
+
+typedef struct rc_conf rc_handle;
+
+#define AUTH_HDR_LEN			20
+#define CHAP_VALUE_LENGTH		16
+
+#define PW_AUTH_UDP_PORT		1645
+#define PW_ACCT_UDP_PORT		1646
+
+#define PW_TYPE_STRING			0
+#define PW_TYPE_INTEGER			1
+#define PW_TYPE_IPADDR			2
+#define PW_TYPE_DATE			3
+#define PW_TYPE_IPV6ADDR		4
+#define PW_TYPE_IPV6PREFIX		5
+
+/* standard RADIUS codes */
+
+#define PW_ACCESS_REQUEST		1
+#define PW_ACCESS_ACCEPT		2
+#define PW_ACCESS_REJECT		3
+#define PW_ACCOUNTING_REQUEST	4
+#define PW_ACCOUNTING_RESPONSE	5
+#define PW_ACCOUNTING_STATUS	6
+#define PW_PASSWORD_REQUEST		7
+#define PW_PASSWORD_ACK			8
+#define PW_PASSWORD_REJECT		9
+#define PW_ACCOUNTING_MESSAGE	10
+#define PW_ACCESS_CHALLENGE		11
+#define PW_STATUS_SERVER		12
+#define PW_STATUS_CLIENT		13
+
+
+/* standard RADIUS attribute-value pairs */
+
+#define PW_ACCESS               244
+
+#define PW_USER_NAME			1	//!< string.
+#define PW_USER_PASSWORD		2	//!< string.
+#define PW_CHAP_PASSWORD		3	//!< string.
+#define PW_NAS_IP_ADDRESS		4	//!< ipaddr.
+#define PW_NAS_PORT			    5	//!< integer.
+#define PW_SERVICE_TYPE			6	//!< integer.
+#define PW_FRAMED_PROTOCOL		7	//!< integer.
+#define PW_FRAMED_IP_ADDRESS	8	//!< ipaddr.
+#define PW_FRAMED_IP_NETMASK	9	//!< ipaddr.
+#define PW_FRAMED_ROUTING		10	//!< integer.
+#define PW_FILTER_ID			11	//!< string.
+#define PW_FRAMED_MTU			12	//!< integer.
+#define PW_FRAMED_COMPRESSION	13	//!< integer.
+#define PW_LOGIN_IP_HOST		14	//!< ipaddr.
+#define PW_LOGIN_SERVICE		15	//!< integer.
+#define PW_LOGIN_PORT			16	//!< integer.
+#define PW_OLD_PASSWORD			17	//!< string */ /* deprecated.
+#define PW_REPLY_MESSAGE		18	//!< string.
+#define PW_LOGIN_CALLBACK_NUMBER    19	//!< string.
+#define PW_FRAMED_CALLBACK_ID		20	//!< string.
+#define PW_EXPIRATION			21	//!< date */ /* deprecated.
+#define PW_FRAMED_ROUTE			22	//!< string.
+#define PW_FRAMED_IPX_NETWORK	23	//!< integer.
+#define PW_STATE			    24	//!< string.
+#define PW_CLASS			    25	//!< string.
+#define PW_VENDOR_SPECIFIC	    26	//!< string.
+#define PW_SESSION_TIMEOUT		27	//!< integer.
+#define PW_IDLE_TIMEOUT			28	//!< integer.
+#define PW_TERMINATION_ACTION	29	//!< integer.
+#define PW_CALLED_STATION_ID	30	//!< string.
+#define PW_CALLING_STATION_ID	31	//!< string.
+#define PW_NAS_IDENTIFIER		32	//!< string.
+#define PW_PROXY_STATE			33	//!< string.
+#define PW_LOGIN_LAT_SERVICE	34	//!< string.
+#define PW_LOGIN_LAT_NODE		35	//!< string.
+#define PW_LOGIN_LAT_GROUP		36	//!< string.
+#define PW_FRAMED_APPLETALK_LINK	37	//!< integer.
+#define PW_FRAMED_APPLETALK_NETWORK	38	//!< integer.
+#define PW_FRAMED_APPLETALK_ZONE	39	//!< string.
+#define PW_ACCT_STATUS_TYPE		    40	//!< integer.
+#define PW_ACCT_DELAY_TIME		    41	//!< integer.
+#define PW_ACCT_INPUT_OCTETS		42	//!< integer.
+#define PW_ACCT_OUTPUT_OCTETS		43	//!< integer.
+#define PW_ACCT_SESSION_ID		    44	//!< string.
+#define PW_ACCT_AUTHENTIC		    45	//!< integer.
+#define PW_ACCT_SESSION_TIME		46	//!< integer.
+#define PW_ACCT_INPUT_PACKETS		47	//!< integer.
+#define PW_ACCT_OUTPUT_PACKETS		48	//!< integer.
+#define PW_ACCT_TERMINATE_CAUSE		49	//!< integer.
+#define PW_ACCT_MULTI_SESSION_ID	50	//!< string.
+#define PW_ACCT_LINK_COUNT		    51	//!< integer.
+#define PW_ACCT_INPUT_GIGAWORDS		52	//!< integer.
+#define PW_ACCT_OUTPUT_GIGAWORDS	53	//!< integer.
+#define PW_EVENT_TIMESTAMP		    55	//!< integer.
+#define PW_EGRESS_VLANID		    56	//!< string.
+#define PW_INGRESS_FILTERS		    57	//!< integer.
+#define PW_EGRESS_VLAN_NAME		    58	//!< string.
+#define PW_USER_PRIORITY_TABLE		59	//!< string.
+#define PW_CHAP_CHALLENGE		    60	//!< string.
+#define PW_NAS_PORT_TYPE		    61	//!< integer.
+#define PW_PORT_LIMIT			    62	//!< integer.
+#define PW_LOGIN_LAT_PORT		    63	//!< string.
+#define PW_TUNNEL_TYPE			    64	//!< string.
+#define PW_TUNNEL_MEDIUM_TYPE		65	//!< integer.
+#define PW_TUNNEL_CLIENT_ENDPOINT	66	//!< string.
+#define PW_TUNNEL_SERVER_ENDPOINT	67	//!< string.
+#define PW_ACCT_TUNNEL_CONNECTION	68	//!< string.
+#define PW_TUNNEL_PASSWORD		    69	//!< string.
+#define PW_ARAP_PASSWORD		    70	//!< string.
+#define PW_ARAP_FEATURES		    71	//!< string.
+#define PW_ARAP_ZONE_ACCESS		    72	//!< integer.
+#define PW_ARAP_SECURITY		    73	//!< integer.
+#define PW_ARAP_SECURITY_DATA		74	//!< string.
+#define PW_PASSWORD_RETRY		    75	//!< integer.
+#define PW_PROMPT			        76	//!< integer.
+#define PW_CONNECT_INFO			    77	//!< string.
+#define PW_CONFIGURATION_TOKEN		78	//!< string.
+#define PW_EAP_MESSAGE			    79	//!< string.
+#define PW_MESSAGE_AUTHENTICATOR	80	//!< string.
+#define PW_TUNNEL_PRIVATE_GROUP_ID	81	//!< string.
+#define PW_TUNNEL_ASSIGNMENT_ID		82	//!< string.
+#define PW_TUNNEL_PREFERENCE		83	//!< string.
+#define PW_ARAP_CHALLENGE_RESPONSE	84	//!< string.
+#define PW_ACCT_INTERIM_INTERVAL	85	//!< integer.
+#define PW_ACCT_TUNNEL_PACKETS_LOST	86	//!< integer.
+#define PW_NAS_PORT_ID_STRING		87	//!< string.
+#define PW_FRAMED_POOL			    88	//!< string.
+#define PW_CHARGEABLE_USER_IDENTITY	89	//!< string.
+#define PW_CUI				        89	//!< string.
+#define PW_TUNNEL_CLIENT_AUTH_ID	90	//!< string.
+#define PW_TUNNEL_SERVER_AUTH_ID	91	//!< string.
+#define PW_NAS_FILTER_RULE		    92	//!< string.
+#define PW_ORIGINATING_LINE_INFO	94	//!< string.
+#define PW_NAS_IPV6_ADDRESS		    95	//!< string.
+#define PW_FRAMED_INTERFACE_ID		96	//!< string.
+#define PW_FRAMED_IPV6_PREFIX		97	//!< string.
+#define PW_LOGIN_IPV6_HOST		    98	//!< string.
+#define PW_FRAMED_IPV6_ROUTE		99	//!< string.
+#define PW_FRAMED_IPV6_POOL		    100	//!< string.
+#define PW_ERROR_CAUSE			    101	//!< integer.
+#define PW_EAP_KEY_NAME			    102	//!< string.
+
+#define PW_FRAMED_IPV6_ADDRESS		168	//!< ipaddr6.
+#define PW_DNS_SERVER_IPV6_ADDRESS	169	//!< ipaddr6.
+#define PW_ROUTE_IPV6_INFORMATION	170	//!< ipv6prefix.
+
+/* Experimental SIP-specific attributes (draft-sterman-aaa-sip-00.txt etc) */
+
+#define PW_DIGEST_RESPONSE		    206	//!< string.
+#define PW_DIGEST_ATTRIBUTES		207	//!< string.
+#define PW_DIGEST_REALM			    1063	//!< string.
+#define PW_DIGEST_NONCE			    1064	//!< string.
+#define PW_DIGEST_METHOD		    1065	//!< string.
+#define PW_DIGEST_URI			    1066	//!< string.
+#define PW_DIGEST_QOP			    1067	//!< string.
+#define PW_DIGEST_ALGORITHM		    1068	//!< string.
+#define PW_DIGEST_BODY_DIGEST		1069	//!< string.
+#define PW_DIGEST_CNONCE		    1070	//!< string.
+#define PW_DIGEST_NONCE_COUNT		1071	//!< string.
+#define PW_DIGEST_USER_NAME		    1072	//!< string.
+
+/* Integer Translations */
+
+/* SERVICE TYPES */
+
+#define PW_LOGIN			    1
+#define PW_FRAMED			    2
+#define PW_CALLBACK_LOGIN		3
+#define PW_CALLBACK_FRAMED		4
+#define PW_OUTBOUND			    5
+#define PW_ADMINISTRATIVE		6
+#define PW_NAS_PROMPT			7
+#define PW_AUTHENTICATE_ONLY	8
+#define PW_CALLBACK_NAS_PROMPT	9
+
+/* FRAMED PROTOCOLS */
+
+#define PW_PPP				1
+#define PW_SLIP				2
+#define PW_ARA				3
+#define PW_GANDALF			4
+#define PW_XYLOGICS			5
+
+/* FRAMED ROUTING VALUES */
+
+#define PW_NONE				0
+#define PW_BROADCAST		1
+#define PW_LISTEN			2
+#define PW_BROADCAST_LISTEN	3
+
+/* FRAMED COMPRESSION TYPES */
+
+#define PW_VAN_JACOBSON_TCP_IP		1
+#define PW_IPX_HEADER_COMPRESSION	2
+
+/* LOGIN SERVICES */
+
+#define PW_TELNET			0
+#define PW_RLOGIN			1
+#define PW_TCP_CLEAR		2
+#define PW_PORTMASTER		3
+#define PW_LAT				4
+#define PW_X25_PAD			5
+#define PW_X25_T3POS		6
+
+/* TERMINATION ACTIONS */
+
+#define PW_DEFAULT			0
+#define PW_RADIUS_REQUEST	1
+
+/* PROHIBIT PROTOCOL */
+
+#define PW_DUMB			    0	//!< 1 and 2 are defined in FRAMED PROTOCOLS.
+#define PW_AUTH_ONLY	    3
+#define PW_ALL			    255
+
+/* ACCOUNTING STATUS TYPES */
+
+#define PW_STATUS_START		1
+#define PW_STATUS_STOP		2
+#define PW_STATUS_ALIVE		3
+#define PW_STATUS_MODEM_START	4
+#define PW_STATUS_MODEM_STOP	5
+#define PW_STATUS_CANCEL	6
+#define PW_ACCOUNTING_ON	7
+#define PW_ACCOUNTING_OFF	8
+
+/* ACCOUNTING TERMINATION CAUSES */
+
+#define PW_USER_REQUEST		1
+#define PW_LOST_CARRIER		2
+#define PW_LOST_SERVICE		3
+#define PW_ACCT_IDLE_TIMEOUT	4
+#define PW_ACCT_SESSION_TIMEOUT	5
+#define PW_ADMIN_RESET		6
+#define PW_ADMIN_REBOOT		7
+#define PW_PORT_ERROR		8
+#define PW_NAS_ERROR		9
+#define PW_NAS_REQUEST		10
+#define PW_NAS_REBOOT		11
+#define PW_PORT_UNNEEDED	12
+#define PW_PORT_PREEMPTED	13
+#define PW_PORT_SUSPENDED	14
+#define PW_SERVICE_UNAVAILABLE	15
+#define PW_CALLBACK		    16
+#define PW_USER_ERROR		17
+#define PW_HOST_REQUEST		18
+
+/* NAS PORT TYPES */
+
+#define PW_ASYNC		    0
+#define PW_SYNC			    1
+#define PW_ISDN_SYNC		2
+#define PW_ISDN_SYNC_V120	3
+#define PW_ISDN_SYNC_V110	4
+#define PW_VIRTUAL		    5
+
+/* AUTHENTIC TYPES */
+
+#define PW_RADIUS	1
+#define PW_LOCAL	2
+#define PW_REMOTE	3
+
+/* Server data structures */
+
+typedef struct dict_attr
+{
+	char              name[NAME_LENGTH + 1];	//!< attribute name.
+	int               value;			//!< attribute index.
+	int               type;				//!< string, int, etc..
+	struct dict_attr *next;
+} DICT_ATTR;
+
+typedef struct dict_value
+{
+	char               attrname[NAME_LENGTH +1];
+	char               name[NAME_LENGTH + 1];
+	int                value;
+	struct dict_value *next;
+} DICT_VALUE;
+
+typedef struct dict_vendor
+{
+	char               vendorname[NAME_LENGTH +1];
+	int                vendorpec;
+	struct dict_vendor *next;
+} DICT_VENDOR;
+
+typedef struct value_pair
+{
+	char               name[NAME_LENGTH + 1];
+	int                attribute;
+	int                type;
+	uint32_t           lvalue;
+	char               strvalue[AUTH_STRING_LEN + 1];
+	struct value_pair *next;
+} VALUE_PAIR;
+
+/* Define return codes from "SendServer" utility */
+
+#define NET_ERR_RC  -3  // Ошибка создания сокета, соединения/отправки/приема
+#define BADRESP_RC	-2  // Неверный пароль
+#define ERROR_RC	-1
+#define OK_RC		0
+#define TIMEOUT_RC	1
+#define REJECT_RC	2  // Неверный логин
+#define USER_RC     3
+#define ADMIN_RC    4
+
+typedef struct send_data /* Used to pass information to sendserver() function */
+{
+	uint8_t        code;		//!< RADIUS packet code.
+	uint8_t        seq_nbr;		//!< Packet sequence number.
+	char           *server;		//!< Name/addrress of RADIUS server.
+	int            svc_port;	//!< RADIUS protocol destination port.
+	char           *secret;		//!< Shared secret of RADIUS server.
+	int            timeout;		//!< Session timeout in seconds.
+	int            retries;
+	VALUE_PAIR     *send_pairs;     //!< More a/v pairs to send.
+	VALUE_PAIR     *receive_pairs;  //!< Where to place received a/v pairs.
+} SEND_DATA;
+
+#ifndef MIN
+#define MIN(a, b)     ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b)     ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX	1024
+#endif
+
+typedef struct env
+{
+	int maxsize, size;
+	char **env;
+} ENV;
+
+#define ENV_SIZE	128
+
+__BEGIN_DECLS
+
+/* Function prototypes */
+
+/* avpair.c */
+
+VALUE_PAIR *rc_avpair_add(rc_handle const *, VALUE_PAIR **, int, void const *, int, int);
+int rc_avpair_assign(VALUE_PAIR *, void const *, int);
+VALUE_PAIR *rc_avpair_new(rc_handle const *, int, void const *, int, int);
+VALUE_PAIR *rc_avpair_gen(rc_handle const *, VALUE_PAIR *, unsigned char const *, int, int);
+VALUE_PAIR *rc_avpair_get(VALUE_PAIR *, int, int);
+void rc_avpair_insert(VALUE_PAIR **, VALUE_PAIR *, VALUE_PAIR *);
+void rc_avpair_free(VALUE_PAIR *);
+int rc_avpair_parse(rc_handle const *, char const *, VALUE_PAIR **);
+int rc_avpair_tostr(rc_handle const *, VALUE_PAIR *, char *, int, char *, int);
+char *rc_avpair_log(rc_handle const *, VALUE_PAIR *, char *buf, size_t buf_len);
+//VALUE_PAIR *rc_avpair_readin(rc_handle const *, FILE *);
+
+/* buildreq.c */
+
+void rc_buildreq(rc_handle const *, SEND_DATA *, int, char *, unsigned short, char *, int, int);
+unsigned char rc_get_id();
+int rc_auth(rc_handle *, uint32_t, VALUE_PAIR *, VALUE_PAIR **, char *);
+int rc_auth_proxy(rc_handle *, VALUE_PAIR *, VALUE_PAIR **, char *);
+int rc_acct(rc_handle *, uint32_t, VALUE_PAIR *);
+int rc_acct_proxy(rc_handle *, VALUE_PAIR *);
+int rc_check(rc_handle *, char *, char *, unsigned short, char *);
+
+int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received,
+    char *msg, int add_nas_port, int request_type);
+
+/* clientid.c */
+
+int rc_read_mapfile(rc_handle *, char const *);
+uint32_t rc_map2id(rc_handle const *, char const *);
+void rc_map2id_free(rc_handle *);
+
+/* config.c */
+
+//rc_handle *rc_read_config(char const *);
+void rc_read_config(rc_handle* rh);
+char *rc_conf_str(rc_handle const *, char const *);
+int rc_conf_int(rc_handle const *, char const *);
+SERVER *rc_conf_srv(rc_handle const *, char const *);
+void rc_config_free(rc_handle *);
+int rc_add_config(rc_handle *, char const *, char const *, char const *, int);
+rc_handle *rc_config_init(rc_handle *);
+int test_config(rc_handle const *, char const *);
+
+/* dict.c */
+
+int rc_read_dictionary(rc_handle *, char const *);
+DICT_ATTR *rc_dict_getattr(rc_handle const *, int);
+DICT_ATTR *rc_dict_findattr(rc_handle const *, char const *);
+DICT_VALUE *rc_dict_findval(rc_handle const *, char const *);
+DICT_VENDOR *rc_dict_findvend(rc_handle const *, char const *);
+DICT_VENDOR *rc_dict_getvend(rc_handle const *, int);
+DICT_VALUE * rc_dict_getval(rc_handle const *, uint32_t, char const *);
+void rc_dict_free(rc_handle *);
+
+/* ip_util.c */
+
+
+int rc_good_ipaddr(char const *);
+unsigned short rc_getport(int);
+int rc_own_hostname(char *, int);
+struct sockaddr;
+int rc_get_srcaddr(struct sockaddr *, const struct sockaddr *);
+
+
+/* log.c */
+
+void rc_openlog(char const *);
+void rc_log(int, char const *, ...);
+
+/* sendserver.c */
+
+int rc_send_server(rc_handle *, SEND_DATA *, char *, unsigned flags);
+
+/* util.c */
+
+void rc_str2tm(char const *, struct tm *);
+char *rc_getifname(rc_handle *, char const *);
+char *rc_getstr(rc_handle *, char const *, int);
+void rc_mdelay(int);
+char *rc_mksid(rc_handle *);
+rc_handle *rc_new(void);
+void rc_destroy(rc_handle *);
+//char *rc_fgetln(FILE *, size_t *);
+double rc_getctime(void);
+
+/* env.c */
+
+struct env *rc_new_env(int);
+void rc_free_env(struct env *);
+int rc_add_env(struct env *, char const *, char const *);
+int rc_import_env(struct env *, char const **);
+
+/* md5.c */
+
+void rc_md5_calc(unsigned char *, unsigned char const *, unsigned int);
+
+__END_DECLS
+
+#endif /* FREERADIUS_CLIENT_H */

+ 189 - 0
thirdparty/FreeRadius/include/includes.h

@@ -0,0 +1,189 @@
+/*
+ * $Id: includes.h,v 1.6 2007/06/21 18:07:22 cparker Exp $
+ *
+ * Copyright (C) 1997 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#ifndef RC_INCLUDES_H
+# define RC_INCLUDES_H
+
+#include "radius_config.h"
+#include "rtc.h"
+#include "rng.h"
+
+/* AIX requires this to be the first thing in the file.  */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# else
+#  ifdef _AIX
+#   pragma alloca
+#  else
+#   ifndef alloca /* predefined by HP cc +Olibcalls */
+     char *alloca ();
+#   endif
+#  endif
+# endif
+#endif
+
+//#include <sys/types.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+# include <stdarg.h>
+#else
+# include <stdarg.h>
+# ifndef HAVE_STRCHR
+#  define strchr index
+#  define strrchr rindex
+# endif
+#endif
+
+/* I realize that this is ugly and unsafe.. :( */
+#ifndef HAVE_SNPRINTF
+# define snprintf(buf, len, format, ...) sprintf(buf, format, __VA_ARGS__)
+#endif
+#ifndef HAVE_VSNPRINTF
+# define vsnprintf(buf, len, format, ap) vsprintf(buf, format, ap)
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_FCNTL_H
+# include <sys/fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+# include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_CRYPT_H
+# include <crypt.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX        1024
+#endif
+
+#ifndef UCHAR_MAX
+# ifdef  __STDC__
+#  define UCHAR_MAX       255U
+# else
+#  define UCHAR_MAX       255
+# endif
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if defined(HAVE_SIGNAL_H)
+# include <signal.h>
+#endif
+#if defined(HAVE_SYS_SIGNAL_H)
+# include <sys/signal.h>
+#endif
+
+#ifdef NEED_SIG_PROTOTYPES
+int sigemptyset(sigset_t *);
+int sigaddset(sigset_t *, int);
+int sigprocmask (int, sigset_t *, sigset_t *);
+#endif
+
+#if HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+#if defined(HAVE_SHADOW_H) && defined(HAVE_SHADOW_PASSWORDS)
+# include <shadow.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+/*
+ * prefer srandom/random over srand/rand as there generator has a
+ * better distribution of the numbers on certain systems.
+ * on Linux both generators are identical.
+ */
+#ifndef HAVE_RANDOM
+# ifdef HAVE_RAND
+# define srandom        srand
+# define random         GetRandomNumber
+# endif
+#endif
+
+/* rlib/lock.c */
+int do_lock_exclusive(FILE *);
+int do_unlock(FILE *);
+
+#endif

+ 53 - 0
thirdparty/FreeRadius/include/messages.h

@@ -0,0 +1,53 @@
+/*
+ * $Id: messages.h,v 1.2 2004/02/23 20:10:39 sobomax Exp $
+ *
+ * Copyright (C) 1995,1996 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+/*
+ * Only messages that the user gets under normal use are in here.
+ * Error messages and such are still in the source code.
+ */
+
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+/* radlogin.c */
+
+#define SC_LOGIN	 "login: "
+#define SC_PASSWORD	 "Password: "
+
+#define SC_TIMEOUT	 "\r\nlogin timed out after %d seconds. Bye.\r\n"
+#define SC_EXCEEDED	 "Maximum login tries exceeded. Go away!\r\n"
+
+#define SC_RADIUS_OK	 "RADIUS: Authentication OK\r\n"
+#define SC_RADIUS_FAILED "RADIUS: Authentication failure\r\n"
+
+#define SC_LOCAL_OK	 "local: Authentication OK\r\n"
+#define SC_LOCAL_FAILED	 "local: Authentication failure\r\n"
+#define SC_NOLOGIN	 "\r\nSystem closed for maintenance. Try again later...\r\n"
+
+#define SC_SERVER_REPLY	 "RADIUS: %s"
+
+#define SC_DEFAULT_ISSUE "(\\I)\r\n\r\n\\S \\R (\\N) (port \\L)\r\n\r\n"
+
+/* radacct.c */
+
+#define SC_ACCT_OK	 "RADIUS accounting OK\r\n"
+#define SC_ACCT_FAILED	 "RADIUS accounting failed (RC=%i)\r\n"
+
+/* radstatus.c */
+
+#define SC_STATUS_FAILED	"RADIUS: Status failure\r\n"
+
+#endif /* MESSAGES_H */

+ 28 - 0
thirdparty/FreeRadius/include/pathnames.h

@@ -0,0 +1,28 @@
+/*
+ * $Id: pathnames.h,v 1.2 2004/02/23 20:10:39 sobomax Exp $
+ *
+ * Copyright (C) 1995,1996 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#ifndef PATHNAMES_H
+#define PATHNAMES_H
+
+#define _PATH_DEV_URANDOM		"/dev/urandom"		/* Linux only */
+#define _PATH_ETC_ISSUE			"/etc/issue"
+
+/* normally defined in the Makefile */
+#ifndef _PATH_ETC_RADIUSCLIENT_CONF
+#  define _PATH_ETC_RADIUSCLIENT_CONF	"/etc/radiusclient.conf"
+#endif
+
+#endif /* PATHNAMES_H */

+ 893 - 0
thirdparty/FreeRadius/lib/avpair.c

@@ -0,0 +1,893 @@
+/*
+ * $Id: avpair.c,v 1.26 2010/06/15 09:22:52 aland Exp $
+ *
+ * Copyright (C) 1995 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#include "util.h"
+#include "def.h"
+
+/** Adds an attribute-value pair to the given list
+ *
+ * @note Always appends the new pair to the end of the list.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param list a #VALUE_PAIR array of values; initially must be %NULL.
+ * @param attrid The attribute of the pair to add (e.g., %PW_USER_NAME).
+ * @param pval the value (e.g., the actual username).
+ * @param len the length of @pval, or -1 if to calculate (in case of strings).
+ * @param vendorpec The vendor ID in case of a vendor specific value - 0 otherwise.
+ * @return pointer to added a/v pair upon success, NULL pointer upon failure.
+ */
+VALUE_PAIR *rc_avpair_add (rc_handle const *rh, VALUE_PAIR **list, int attrid, void const *pval, int len, int vendorpec)
+{
+	VALUE_PAIR     *vp;
+
+	vp = rc_avpair_new (rh, attrid, pval, len, vendorpec);
+
+	if (vp != NULL)
+	{
+		rc_avpair_insert (list, NULL, vp);
+	}
+
+	return vp;
+}
+
+/** Assigns the given value to an attribute-value pair
+ *
+ * @param vp a pointer to a #VALUE_PAIR structure.
+ * @param pval the value (e.g., the actual username).
+ * @param len the length of @pval, or -1 if to calculate (in case of strings).
+ * @return 0 on success or -1 on failure.
+ */
+int rc_avpair_assign (VALUE_PAIR *vp, void const *pval, int len)
+{
+#if 1
+	switch (vp->type)
+	{
+		case PW_TYPE_STRING:
+			if (len == -1)
+				len = (uint32_t)strlen((char const *)pval);
+			if (len > AUTH_STRING_LEN) {
+		        	rc_log(LOG_ERR, "rc_avpair_assign: bad attribute length");
+		        	return -1;
+			}
+			memcpy(vp->strvalue, (char const *)pval, len);
+			vp->strvalue[len] = '\0';
+			vp->lvalue = len;
+			break;
+
+		case PW_TYPE_DATE:
+		case PW_TYPE_INTEGER:
+	        case PW_TYPE_IPADDR:
+			vp->lvalue = * (uint32_t *) pval;
+			break;
+	        case PW_TYPE_IPV6ADDR:
+			if (len != 16) {
+		        	rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 length");
+		        	return -1;
+			}
+			memcpy(vp->strvalue, (char const *)pval, len);
+			vp->lvalue = len;
+			break;
+
+	        case PW_TYPE_IPV6PREFIX:
+			if (len < 2 || len > 18) {
+		        	rc_log(LOG_ERR, "rc_avpair_assign: bad IPv6 prefix length");
+		        	return -1;
+			}
+			memcpy(vp->strvalue, (char const *)pval, len);
+			vp->lvalue = len;
+			break;
+
+		default:
+			rc_log(LOG_ERR, "rc_avpair_assign: unknown attribute %d", vp->type);
+			return -1;
+	}
+#endif    
+	return 0;
+}
+
+/** Make a new attribute-value pair with given parameters
+ *
+ * @param rh a handle to parsed configuration.
+ * @param attrid The attribute of the pair to add (e.g., %PW_USER_NAME).
+ * @param pval the value (e.g., the actual username).
+ * @param len the length of pval, or -1 if to calculate (in case of strings).
+ * @param vendorpec The vendor ID in case of a vendor specific value - 0 otherwise.
+ * @return pointer to generated a/v pair when successful, NULL when failure.
+ */
+VALUE_PAIR *rc_avpair_new (rc_handle const *rh, int attrid, void const *pval, int len, int vendorpec)
+{
+ 
+	VALUE_PAIR     *vp = NULL;
+	DICT_ATTR      *pda;
+
+	attrid = attrid | (vendorpec << 16);
+	if ((pda = rc_dict_getattr (rh, attrid)) == NULL)
+	{
+		rc_log(LOG_ERR,"rc_avpair_new: unknown attribute %d", attrid);
+		return NULL;
+	}
+	if (vendorpec != 0 && rc_dict_getvend(rh, vendorpec) == NULL)
+	{
+		rc_log(LOG_ERR,"rc_avpair_new: unknown Vendor-Id %d", vendorpec);
+		return NULL;
+	}
+	if ((vp = malloc (sizeof (VALUE_PAIR))) != NULL)
+	{
+		strlcpy (vp->name, pda->name, sizeof (vp->name));
+		vp->attribute = attrid;
+		vp->next = NULL;
+		vp->type = pda->type;
+		if (rc_avpair_assign (vp, pval, len) == 0)
+		{
+			/* XXX: Fix up Digest-Attributes */
+			switch (vp->attribute) {
+			case PW_DIGEST_REALM:
+			case PW_DIGEST_NONCE:
+			case PW_DIGEST_METHOD:
+			case PW_DIGEST_URI:
+			case PW_DIGEST_QOP:
+			case PW_DIGEST_ALGORITHM:
+			case PW_DIGEST_BODY_DIGEST:
+			case PW_DIGEST_CNONCE:
+			case PW_DIGEST_NONCE_COUNT:
+			case PW_DIGEST_USER_NAME:
+				/* overlapping! */
+				if (vp->lvalue > AUTH_STRING_LEN - 2)
+					vp->lvalue = AUTH_STRING_LEN - 2;
+				memmove(&vp->strvalue[2], &vp->strvalue[0], vp->lvalue);
+				vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
+				vp->lvalue += 2;
+				vp->strvalue[1] = vp->lvalue;
+				vp->strvalue[vp->lvalue] = '\0';
+				vp->attribute = PW_DIGEST_ATTRIBUTES;
+			default:
+				break;
+			}
+			return vp;
+		}
+		free (vp);
+		vp = NULL;
+	}
+	else
+	{
+		rc_log(LOG_CRIT,"rc_avpair_new: out of memory");
+	}
+
+	return vp;
+}
+
+/** Takes attribute/value pairs from buffer and builds a value_pair list using allocated memory
+ *
+ * @note Uses recursion.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param pair a pointer to a #VALUE_PAIR structure.
+ * @param ptr the value (e.g., the actual username).
+ * @param length the length of ptr, or -1 if to calculate (in case of strings).
+ * @param vendorpec The vendor ID in case of a vendor specific value - 0 otherwise.
+ * @return value_pair list or %NULL on failure.
+ */
+VALUE_PAIR *rc_avpair_gen(rc_handle const *rh, VALUE_PAIR *pair, unsigned char const *ptr,
+			  int length, int vendorpec)
+{
+#if 1
+	int attribute, attrlen, x_len;
+	unsigned char const *x_ptr;
+	uint32_t lvalue;
+	DICT_ATTR *attr;
+	VALUE_PAIR *rpair;
+	char buffer[(AUTH_STRING_LEN * 2) + 1];
+	/* For hex string conversion. */
+	char hex[3];
+
+	if (length < 2) {
+		rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
+		    "invalid length");
+		goto shithappens;
+	}
+	attrlen = ptr[1];
+	if (length < attrlen || attrlen < 2) {
+		rc_log(LOG_ERR, "rc_avpair_gen: received attribute with "
+		    "invalid length");
+		goto shithappens;
+	}
+
+	/* Advance to the next attribute and process recursively */
+	if (length != attrlen) {
+		pair = rc_avpair_gen(rh, pair, ptr + attrlen, length - attrlen,
+		    vendorpec);
+		if (pair == NULL)
+			return NULL;
+	}
+
+	/* Actual processing */
+	attribute = ptr[0] | (vendorpec << 16);
+	ptr += 2;
+	attrlen -= 2;
+
+	/* VSA */
+	if (attribute == PW_VENDOR_SPECIFIC) {
+		if (attrlen < 4) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received VSA "
+			    "attribute with invalid length");
+			goto skipit;
+		}
+		memcpy(&lvalue, ptr, 4);
+		vendorpec = ntohl(lvalue);
+		if (rc_dict_getvend(rh, vendorpec) == NULL) {
+			/* Warn and skip over the unknown VSA */
+			rc_log(LOG_WARNING, "rc_avpair_gen: received VSA "
+			    "attribute with unknown Vendor-Id %d", vendorpec);
+			goto skipit;
+		}
+		/* Process recursively */
+		return rc_avpair_gen(rh, pair, ptr + 4, attrlen - 4,
+		    vendorpec);
+	}
+
+	/* Normal */
+	attr = rc_dict_getattr(rh, attribute);
+	if (attr == NULL) {
+		buffer[0] = '\0';	/* Initial length. */
+		x_ptr = ptr;
+		for (x_len = attrlen; x_len > 0; x_len--, x_ptr++) {
+			snprintf(hex, sizeof(hex), "%2.2X", x_ptr[0]);
+			strcat(buffer, hex);
+		}
+		if (vendorpec == 0) {
+			rc_log(LOG_WARNING, "rc_avpair_gen: received "
+			    "unknown attribute %d of length %d: 0x%s",
+			    attribute, attrlen + 2, buffer);
+		} else {
+			rc_log(LOG_WARNING, "rc_avpair_gen: received "
+			    "unknown VSA attribute %d, vendor %d of "
+			    "length %d: 0x%s", attribute & 0xffff,
+			    VENDOR(attribute), attrlen + 2, buffer);
+		}
+		goto skipit;
+	}
+
+	rpair = malloc(sizeof(*rpair));
+	if (rpair == NULL) {
+		rc_log(LOG_CRIT, "rc_avpair_gen: out of memory");
+		goto shithappens;
+	}
+	memset(rpair, '\0', sizeof(*rpair));
+
+	/* Insert this new pair at the beginning of the list */
+	rpair->next = pair;
+	pair = rpair;
+	strcpy(pair->name, attr->name);
+	pair->attribute = attr->value;
+	pair->type = attr->type;
+
+	switch (attr->type) {
+	case PW_TYPE_STRING:
+		memcpy(pair->strvalue, (char *)ptr, (size_t)attrlen);
+		pair->strvalue[attrlen] = '\0';
+		pair->lvalue = attrlen;
+		break;
+
+	case PW_TYPE_INTEGER:
+		if (attrlen != 4) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received INT "
+			    "attribute with invalid length");
+			goto skipit;
+		}
+	case PW_TYPE_IPADDR:
+		if (attrlen != 4) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received IPADDR"
+			    " attribute with invalid length");
+			goto skipit;
+		}
+		memcpy((char *)&lvalue, (char *)ptr, 4);
+		pair->lvalue = ntohl(lvalue);
+		break;
+	case PW_TYPE_IPV6ADDR:
+		if (attrlen != 16) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received IPV6ADDR"
+			    " attribute with invalid length");
+			goto skipit;
+		}
+		memcpy(pair->strvalue, (char *)ptr, 16);
+		pair->lvalue = attrlen;
+		break;
+	case PW_TYPE_IPV6PREFIX:
+		if (attrlen > 18 || attrlen < 2) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received IPV6PREFIX"
+			    " attribute with invalid length: %d", attrlen);
+			goto skipit;
+		}
+		memcpy(pair->strvalue, (char *)ptr, attrlen);
+		pair->lvalue = attrlen;
+		break;
+	case PW_TYPE_DATE:
+		if (attrlen != 4) {
+			rc_log(LOG_ERR, "rc_avpair_gen: received DATE "
+			    "attribute with invalid length");
+			goto skipit;
+		}
+
+	default:
+		rc_log(LOG_WARNING, "rc_avpair_gen: %s has unknown type",
+		    attr->name);
+		goto skipit;
+	}
+
+skipit:
+	return pair;
+
+shithappens:
+	while (pair != NULL) {
+		rpair = pair->next;
+		free(pair);
+		pair = rpair;
+	}
+#endif    
+	return NULL;
+}
+
+/** Find the first attribute value-pair (which matches the given attribute) from the specified value-pair list
+ *
+ * @param vp a pointer to a #VALUE_PAIR structure.
+ * @param attrid The attribute of the pair to find (e.g., %PW_USER_NAME).
+ * @param vendorpec The vendor ID in case of a vendor specific value - 0 otherwise.
+ * @return the value pair found.
+ */
+VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, int attrid, int vendorpec)
+{
+	for (; vp != NULL && !(ATTRID(vp->attribute) == ATTRID(attrid) &&
+	    VENDOR(vp->attribute) == vendorpec); vp = vp->next)
+	{
+		continue;
+	}
+  
+	return vp;
+}
+
+/** Insert a VALUE_PAIR into a list
+ *
+ * Given the address of an existing list "a" and a pointer to an entry "p" in that list, add the value pair "b" to
+ * the "a" list after the "p" entry.  If "p" is NULL, add the value pair "b" to the end of "a".
+ *
+ * @param a a #VALUE_PAIR array of values.
+ * @param p a pointer to a #VALUE_PAIR in a.
+ * @param b The #VALUE_PAIR pointer to add in a.
+ */
+void rc_avpair_insert(VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
+{
+	VALUE_PAIR     *this_node = NULL;
+	VALUE_PAIR     *vp;
+
+	if (b->next != NULL)
+	{
+		rc_log(LOG_CRIT, "rc_avpair_insert: value pair (0x%p) next ptr. (0x%p) not NULL", b, b->next);
+		abort ();
+	}
+
+	if (*a == NULL)
+	{
+		*a = b;
+		return;
+	}
+
+	vp = *a;
+
+	if ( p == NULL) /* run to end of "a" list */
+	{
+		while (vp != NULL)
+		{
+			this_node = vp;
+			vp = vp->next;
+		}
+	}
+	else /* look for the "p" entry in the "a" list */
+	{
+		this_node = *a;
+		while (this_node != NULL)
+		{
+			if (this_node == p)
+			{
+				break;
+			}
+			this_node = this_node->next;
+		}
+	}
+
+	b->next = this_node->next;
+	this_node->next = b;
+
+	return;
+}
+
+/** Frees all value_pairs in the list
+ *
+ * @param pair a pointer to a VALUE_PAIR structure.
+ */
+void rc_avpair_free (VALUE_PAIR *pair)
+{
+#if 0  
+	VALUE_PAIR     *next;
+
+	while (pair != NULL)
+	{
+		next = pair->next;
+		free (pair);
+		pair = next;
+	}
+#endif    
+}
+
+/** Copy a data field from the buffer
+ *
+ * Advance the buffer past the data field. Ensure that no more than len - 1 bytes are copied and that resulting
+ * string is terminated with '\0'.
+ *
+ * @param string the provided string to copy.
+ * @param uptr the current position of the buffer.
+ * @param stopat characters to which parsing should stop.
+ * @param len the maximum length of string.
+ */
+static void rc_fieldcpy(char *string, char const **uptr, char const *stopat, size_t len)
+{
+#if 0  
+	char const *ptr, *estring;
+
+	ptr = *uptr;
+	estring = string + len - 1;
+	if (*ptr == '"')
+	{
+		ptr++;
+		while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
+		{
+			if (string < estring)
+				*string++ = *ptr;
+			ptr++;
+		}
+		if (*ptr == '"')
+		{
+			ptr++;
+		}
+		*string = '\0';
+		*uptr = ptr;
+		return;
+	}
+
+	while (*ptr != '\0' && strchr(stopat, *ptr) == NULL)
+	{
+		if (string < estring)
+			*string++ = *ptr;
+		ptr++;
+	}
+	*string = '\0';
+	*uptr = ptr;
+#endif
+	return;
+}
+
+#define PARSE_MODE_NAME		0
+#define PARSE_MODE_EQUAL	1
+#define PARSE_MODE_VALUE	2
+#define PARSE_MODE_INVALID	3
+
+/** Parses the buffer to extract the attribute-value pairs
+ *
+ * @param rh a handle to parsed configuration.
+ * @param buffer the buffer to be parsed.
+ * @param first_pair an allocated array of values.
+ * @return 0 on successful parse of attribute-value pair, or -1 on syntax (or other) error detected.
+ */
+int rc_avpair_parse (rc_handle const *rh, char const *buffer, VALUE_PAIR **first_pair)
+{
+#if 0  
+	int             mode;
+	char            attrstr[AUTH_ID_LEN];
+	char            valstr[AUTH_STRING_LEN + 1], *p;
+	DICT_ATTR      *attr = NULL;
+	DICT_VALUE     *dval;
+	VALUE_PAIR     *pair;
+	VALUE_PAIR     *link;
+	struct tm      *tm;
+	time_t          timeval;
+
+	mode = PARSE_MODE_NAME;
+	while (*buffer != '\n' && *buffer != '\0')
+	{
+		if (*buffer == ' ' || *buffer == '\t')
+		{
+			buffer++;
+			continue;
+		}
+
+		switch (mode)
+		{
+		    case PARSE_MODE_NAME:		/* Attribute Name */
+			rc_fieldcpy (attrstr, &buffer, " \t\n=,", sizeof(attrstr));
+			if ((attr =
+				rc_dict_findattr (rh, attrstr)) == NULL)
+			{
+				rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute");
+				if (*first_pair) {
+					rc_avpair_free(*first_pair);
+					*first_pair = NULL;
+				}
+				return -1;
+			}
+			mode = PARSE_MODE_EQUAL;
+			break;
+
+		    case PARSE_MODE_EQUAL:		/* Equal sign */
+			if (*buffer == '=')
+			{
+				mode = PARSE_MODE_VALUE;
+				buffer++;
+			}
+			else
+			{
+				rc_log(LOG_ERR, "rc_avpair_parse: missing or misplaced equal sign");
+				if (*first_pair) {
+					rc_avpair_free(*first_pair);
+					*first_pair = NULL;
+				}
+				return -1;
+			}
+			break;
+
+		    case PARSE_MODE_VALUE:		/* Value */
+			rc_fieldcpy (valstr, &buffer, " \t\n,", sizeof(valstr));
+
+			if ((pair = malloc (sizeof (VALUE_PAIR))) == NULL)
+			{
+				rc_log(LOG_CRIT, "rc_avpair_parse: out of memory");
+				if (*first_pair) {
+					rc_avpair_free(*first_pair);
+					*first_pair = NULL;
+				}
+				return -1;
+			}
+			strcpy (pair->name, attr->name);
+			pair->attribute = attr->value;
+			pair->type = attr->type;
+
+			switch (pair->type)
+			{
+
+			    case PW_TYPE_STRING:
+				strcpy (pair->strvalue, valstr);
+				pair->lvalue = (uint32_t)strlen(valstr);
+				break;
+
+			    case PW_TYPE_INTEGER:
+				if (isdigit (*valstr))
+				{
+					pair->lvalue = atoi (valstr);
+				}
+				else
+				{
+					if ((dval = rc_dict_findval (rh, valstr))
+							== NULL)
+					{
+						rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute value: %s", valstr);
+						if (*first_pair) {
+							rc_avpair_free(*first_pair);
+							*first_pair = NULL;
+						}
+						free (pair);
+						return -1;
+					}
+					else
+					{
+						pair->lvalue = dval->value;
+					}
+				}
+				break;
+
+			    case PW_TYPE_IPADDR:
+			    	if (inet_pton(AF_INET, valstr, &pair->lvalue) == 0) {
+			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv4 address %s", valstr);
+			    		free(pair);
+			    		return -1;
+			    	}
+
+                                pair->lvalue = ntohl(pair->lvalue);
+				break;
+
+			    case PW_TYPE_IPV6ADDR:
+			    	if (inet_pton(AF_INET6, valstr, pair->strvalue) == 0) {
+			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 address %s", valstr);
+			    		free(pair);
+			    		return -1;
+			    	}
+				pair->lvalue = 16;
+				break;
+
+			    case PW_TYPE_IPV6PREFIX:
+			    	p = strchr(valstr, '/');
+			    	if (p == NULL) {
+			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
+			    		free(pair);
+			    		return -1;
+			    	}
+			    	*p = 0;
+			    	p++;
+			    	pair->strvalue[0] = 0;
+			    	pair->strvalue[1] = atoi(p);
+
+			    	if (inet_pton(AF_INET6, valstr, pair->strvalue+2) == 0) {
+			    		rc_log(LOG_ERR, "rc_avpair_parse: invalid IPv6 prefix %s", valstr);
+			    		free(pair);
+			    		return -1;
+			    	}
+				pair->lvalue = 2+16;
+				break;
+
+			    case PW_TYPE_DATE:
+				timeval = time (0);
+				tm = localtime (&timeval);
+				tm->tm_hour = 0;
+				tm->tm_min = 0;
+				tm->tm_sec = 0;
+				rc_str2tm (valstr, tm);
+#ifdef TIMELOCAL
+				pair->lvalue = (uint32_t) timelocal (tm);
+#else	/* TIMELOCAL */
+				pair->lvalue = (uint32_t) mktime (tm);
+#endif	/* TIMELOCAL */
+				break;
+
+			    default:
+				rc_log(LOG_ERR, "rc_avpair_parse: unknown attribute type %d", pair->type);
+				if (*first_pair) {
+					rc_avpair_free(*first_pair);
+					*first_pair = NULL;
+				}
+				free (pair);
+				return -1;
+			}
+
+			/* XXX: Fix up Digest-Attributes */
+			switch (pair->attribute) {
+			case PW_DIGEST_REALM:
+			case PW_DIGEST_NONCE:
+			case PW_DIGEST_METHOD:
+			case PW_DIGEST_URI:
+			case PW_DIGEST_QOP:
+			case PW_DIGEST_ALGORITHM:
+			case PW_DIGEST_BODY_DIGEST:
+			case PW_DIGEST_CNONCE:
+			case PW_DIGEST_NONCE_COUNT:
+			case PW_DIGEST_USER_NAME:
+				/* overlapping! */
+				if (pair->lvalue > AUTH_STRING_LEN - 2)
+					pair->lvalue = AUTH_STRING_LEN - 2;
+				memmove(&pair->strvalue[2], &pair->strvalue[0], pair->lvalue);
+				pair->strvalue[0] = pair->attribute - PW_DIGEST_REALM + 1;
+				pair->lvalue += 2;
+				pair->strvalue[1] = pair->lvalue;
+				pair->strvalue[pair->lvalue] = '\0';
+				pair->attribute = PW_DIGEST_ATTRIBUTES;
+			}
+
+			pair->next = NULL;
+
+			if (*first_pair == NULL)
+			{
+				*first_pair = pair;
+			}
+			else
+			{
+				link = *first_pair;
+				while (link->next != NULL)
+				{
+					link = link->next;
+				}
+				link->next = pair;
+			}
+
+			mode = PARSE_MODE_NAME;
+			break;
+
+		    default:
+			mode = PARSE_MODE_NAME;
+			break;
+		}
+	}
+#endif
+	return 0;
+}
+
+/** Translate an av_pair into two strings
+ *
+ * @param rh a handle to parsed configuration.
+ * @param pair a pointer to a VALUE_PAIR structure.
+ * @param name the name of the pair.
+ * @param ln the size of name.
+ * @param value the value of the pair.
+ * @param lv the size of value.
+ * @return 0 on success, -1 on failure.
+ */
+int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
+{
+#if 0  
+	DICT_VALUE     *dval;
+	char            buffer[32];
+	struct in_addr  inad;
+	unsigned char  *ptr;
+	unsigned int    pos;
+
+	*name = *value = '\0';
+
+	if (!pair || pair->name[0] == '\0') {
+		rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty");
+		return -1;
+	}
+
+	strlcpy(name, pair->name, (size_t) ln);
+
+	switch (pair->type)
+	{
+	    case PW_TYPE_STRING:
+	    	lv--;
+	    	pos = 0;
+		ptr = (unsigned char *) pair->strvalue;
+		if (pair->attribute == PW_DIGEST_ATTRIBUTES) {
+			pair->strvalue[*(ptr + 1)] = '\0';
+			ptr += 2;
+		}
+		while (*ptr != '\0')
+		{
+			if (!(isprint (*ptr)))
+			{
+				if (lv >= 4) {
+					snprintf (&value[pos], lv, "\\%03o", *ptr);
+					pos += 4;
+					lv -= 4;
+				} else {
+					break;
+				}
+			}
+			else
+			{
+				if (lv > 0) {
+					value[pos++] = *ptr;
+					lv--;
+				} else {
+					break;
+				}
+			}
+			ptr++;
+		}
+		if (lv > 0)
+			value[pos++] = 0;
+		else
+			value[pos-1] = 0;
+		break;
+
+	    case PW_TYPE_INTEGER:
+		dval = rc_dict_getval (rh, pair->lvalue, pair->name);
+		if (dval != NULL)
+		{
+			strlcpy(value, dval->name, (size_t) lv);
+		}
+		else
+		{
+			snprintf(value, lv, "%ld", (long int)pair->lvalue);
+		}
+		break;
+
+	    case PW_TYPE_IPADDR:
+		inad.s_addr = htonl(pair->lvalue);
+		strlcpy (value, inet_ntoa (inad), (size_t) lv);
+		break;
+
+	    case PW_TYPE_IPV6ADDR:
+	    	if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL)
+	    		return -1;
+		break;
+
+	    case PW_TYPE_IPV6PREFIX: {
+	    	uint8_t ip[16];
+	    	char txt[48];
+	    	if (pair->lvalue < 2)
+	    		return -1;
+
+	    	memset(ip, 0, sizeof(ip));
+	    	memcpy(ip, pair->strvalue+2, pair->lvalue-2);
+
+	    	if (inet_ntop(AF_INET6, ip, txt, sizeof(txt)) == NULL)
+	    		return -1;
+		snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]);
+
+		break;
+	    }
+	    case PW_TYPE_DATE:
+		strftime (value, lv, "%m/%d/%y %H:%M:%S",
+			  gmtime ((time_t *) & pair->lvalue));
+		break;
+
+	    default:
+		rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type);
+		return -1;
+		break;
+	}
+#endif
+	return 0;
+}
+
+/** Format a sequence of attribute value pairs into a printable string
+ *
+ * The caller should provide a storage buffer and the buffer length.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param pair a pointer to a #VALUE_PAIR structure.
+ * @param buf will hold the string output of the pair.
+ * @param len the size of buf.
+ * @return a pointer to provided storage buffer.
+ */
+char *rc_avpair_log(rc_handle const *rh, VALUE_PAIR *pair, char *buf, size_t buf_len)
+{
+#if 0  
+	size_t len, nlen;
+	VALUE_PAIR *vp;
+	char name[33], value[256];
+
+	len = 0;
+	for (vp = pair; vp != NULL; vp = vp->next) {
+		if (rc_avpair_tostr(rh, vp, name, sizeof(name), value,
+		    sizeof(value)) == -1)
+		        return NULL;
+		nlen = len + 32 + 3 + strlen(value) + 2 + 2;
+		if(nlen<buf_len-1) {
+			sprintf(buf + len, "%-32s = '%s'\n", name, value);
+		} else return buf;
+		len = nlen - 1;
+	}
+#endif    
+	return buf;
+}
+
+/** Get a sequence of attribute value pairs from the file input and make them into a list of value_pairs
+ *
+ * @param rh a handle to parsed configuration.
+ * @param input a %FILE handle.
+ * @return the array of value pairs.
+ */
+VALUE_PAIR *rc_avpair_readin(rc_handle const *rh, FILE *input)
+{
+	VALUE_PAIR *vp = NULL;
+#if 0  
+	char buffer[1024], *q;
+
+	while (fgets(buffer, sizeof(buffer), input) != NULL)
+	{
+		q = buffer;
+
+		while(*q && isspace(*q)) q++;
+
+		if ((*q == '\n') || (*q == '#') || (*q == '\0'))
+			continue;
+
+		if (rc_avpair_parse(rh, q, &vp) < 0) {
+			rc_log(LOG_ERR, "rc_avpair_readin: malformed attribute: %s", buffer);
+			rc_avpair_free(vp);
+			return NULL;
+		}
+	}
+#endif
+	return vp;
+}

+ 178 - 0
thirdparty/FreeRadius/lib/buildreq.c

@@ -0,0 +1,178 @@
+/*
+ * $Id: buildreq.c,v 1.17 2010/02/04 10:27:09 aland Exp $
+ *
+ * Copyright (C) 1995,1997 Lars Fenneberg
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#include "util.h"
+
+/** Build a skeleton RADIUS request using information from the config file
+ *
+ * @param rh a handle to parsed configuration.
+ * @param data a pointer to a #SEND_DATA structure.
+ * @param code one of standard RADIUS codes (e.g., %PW_ACCESS_REQUEST).
+ * @param server the name of the server.
+ * @param port the server's port number.
+ * @param secret the secret used by the server.
+ * @param timeout the timeout in seconds of a message.
+ * @param retries the number of retries.
+ */
+void rc_buildreq(rc_handle const *rh, SEND_DATA *data, int code, char *server, unsigned short port,
+		 char *secret, int timeout, int retries)
+{
+	data->server = server;
+	data->secret = secret;
+	data->svc_port = port;
+	data->seq_nbr = rc_get_id();
+	data->timeout = timeout;
+	data->retries = retries;
+	data->code = code;
+}
+
+/** Generates a random ID
+ *
+ * @return the random ID.
+ */
+unsigned char rc_get_id()
+{
+	return (unsigned char)(random() & UCHAR_MAX);
+}
+
+/** Builds an authentication/accounting request for port id client_port with the value_pairs send and submits it to a server
+ *
+ * @param rh a handle to parsed configuration.
+ * @param client_port the client port number to use (may be zero to use any available).
+ * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME).
+ * @param received an allocated array of received values.
+ * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of any
+ *	%PW_REPLY_MESSAGE received.
+ * @param add_nas_port if non-zero it will include %PW_NAS_PORT in sent pairs.
+ * @param request_type one of standard RADIUS codes (e.g., %PW_ACCESS_REQUEST).
+ * @return received value_pairs in received, messages from the server in msg and %OK_RC (0) on success, negative
+ *	on failure as return value.
+ */
+int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received,
+	   char *msg, int add_nas_port, int request_type)
+{
+	SEND_DATA   data;
+    VALUE_PAIR* myVp;
+	SERVER		*aaaserver;
+	int		    timeout = rc_conf_int(rh, "radius_timeout");
+	int		    retries = rc_conf_int(rh, "radius_retries");
+	int		    radius_deadtime = rc_conf_int(rh, "radius_deadtime");
+	unsigned	type;
+    int         result;
+
+    SERVER myServer;
+   
+    myVp = rc_avpair_get(send, PW_USER_PASSWORD, 0);
+    myServer.secret[0] = myVp->name;
+       
+    aaaserver = &myServer;
+    type = AUTH;
+    
+    if (aaaserver == NULL)
+		return ERROR_RC;
+
+	data.send_pairs = send;
+	data.receive_pairs = NULL;
+    
+    if (add_nas_port != 0) {
+		// Fill in NAS-Port
+		if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT,
+		    &client_port, 0, 0) == NULL)
+			return ERROR_RC;
+	}
+    
+	if (data.receive_pairs != NULL) {
+		rc_avpair_free(data.receive_pairs);
+		data.receive_pairs = NULL;
+	}
+	rc_buildreq(rh, &data, request_type, aaaserver->name[0],
+		    aaaserver->port[0], aaaserver->secret[0], timeout, retries);
+
+    // Делаем 3 попытки если есть какие-либо проблемы с обменом
+    for (uint8_t i = 0; i < 3; i++)
+    {
+        //printf ("Radius trying\r\n");
+        result = rc_send_server(rh, &data, msg, type);     
+                
+        if (result != NET_ERR_RC)
+            break;
+    }
+    
+    return result;
+    
+}
+
+/** Builds an authentication request for port id client_port with the value_pairs send and submits it to a server
+ *
+ * @param rh a handle to parsed configuration.
+ * @param client_port the client port number to use (may be zero to use any available).
+ * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME).
+ * @param received an allocated array of received values.
+ * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of any
+ *	%PW_REPLY_MESSAGE received.
+ * @return received value_pairs in @received, messages from the server in msg (if non-NULL),
+ *	and %OK_RC (0) on success, negative on failure as return value.
+ */
+int rc_auth(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received,
+    char *msg)
+{
+
+	//return rc_aaa(rh, client_port, send, received, msg, 1, PW_ACCESS_REQUEST);
+    return rc_aaa(rh, client_port, send, received, msg, 0, PW_ACCESS_REQUEST);
+}
+
+/** Builds an authentication request for proxying
+ *
+ * Builds an authentication request with the value_pairs send and submits it to a server.
+ * Works for a proxy; does not add IP address, and does does not rely on config file.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param client_port the client port number to use (may be zero to use any available).
+ * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME).
+ * @param received an allocated array of received values.
+ * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of
+ *	any %PW_REPLY_MESSAGE received.
+ * @return received value_pairs in @received, messages from the server in msg (if non-NULL)
+ *	and %OK_RC (0) on success, negative on failure as return value.
+ */
+int rc_auth_proxy(rc_handle *rh, VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
+{
+	return rc_aaa(rh, 0, send, received, msg, 0, PW_ACCESS_REQUEST);
+}
+
+/** Builds an accounting request for port id client_port with the value_pairs at send
+ *
+ * @note NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled in by this function, the rest has to be supplied.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param client_port the client port number to use (may be zero to use any available).
+ * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME).
+ * @return received value_pairs in @received, and %OK_RC (0) on success, negative on failure as return value.
+ */
+int rc_acct(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send)
+{
+	return rc_aaa(rh, client_port, send, NULL, NULL, 1, PW_ACCOUNTING_REQUEST);
+}
+
+/** Builds an accounting request with the value_pairs at send
+ *
+ * @param rh a handle to parsed configuration.
+ * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME).
+ * @return %OK_RC (0) on success, negative on failure as return value.
+ */
+int rc_acct_proxy(rc_handle *rh, VALUE_PAIR *send)
+{
+
+	return rc_aaa(rh, 0, send, NULL, NULL, 0, PW_ACCOUNTING_REQUEST);
+}
+

+ 943 - 0
thirdparty/FreeRadius/lib/config.c

@@ -0,0 +1,943 @@
+/*
+ * $Id: config.c,v 1.23 2010/04/28 14:26:15 aland Exp $
+ *
+ * Copyright (C) 1995,1996,1997 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#include <fr_options.h>
+#include "util.h"
+
+extern OPTION      rcOptions;
+
+/** Find an option in the option list
+ *
+ * @param rh a handle to parsed configuration.
+ * @param optname the name of the option.
+ * @param type the option type.
+ * @return pointer to option on success, NULL otherwise.
+ */
+static OPTION *find_option(rc_handle const *rh, char const *optname, unsigned int type)
+{
+	int 	i;
+
+	/* there're so few options that a binary search seems not necessary */
+	for (i = 0; i < NUM_OPTIONS; i++) {
+		if (!strcmp(rh->config_options[i].name, optname) &&
+		    (rh->config_options[i].type & type))
+		{
+		    	return &rh->config_options[i];
+		}
+	}
+
+	return NULL;
+}
+
+/** Set a specific option doing type conversions
+ *
+ * @param filename the name of the config file (for logging purposes).
+ * @param line the line number in the file.
+ * @param p Value.
+ * @return 0 on success, -1 on failure.
+ */
+static int set_option_str(char const *filename, int line, OPTION *option, char const *p)
+{
+#if 0
+	if (p) {
+		option->val = (void *) strdup(p);
+		if (option->val == NULL) {
+			rc_log(LOG_CRIT, "read_config: out of memory");
+			return -1;
+		}
+	} else {
+		option->val = NULL;
+	}
+
+	return 0;
+#endif
+}
+
+static int set_option_int(char const *filename, int line, OPTION *option, char const *p)
+{
+	int *iptr;
+
+	if (p == NULL) {
+		rc_log(LOG_ERR, "%s: line %d: bogus option value", filename, line);
+		return -1;
+	}
+
+	if ((iptr = malloc(sizeof(*iptr))) == NULL) {
+		rc_log(LOG_CRIT, "read_config: out of memory");
+		return -1;
+	}
+
+	*iptr = atoi(p);
+	option->val = (void *) iptr;
+
+	return 0;
+}
+
+static int set_option_srv(char const *filename, int line, OPTION *option, char const *p)
+{
+#if 0  
+	SERVER *serv;
+	char *p_pointer;
+	char *p_dupe;
+	char *p_save;
+	char *q;
+	char *s;
+	struct servent *svp;
+
+	p_dupe = strdup(p);
+
+	if (p_dupe == NULL) {
+		rc_log(LOG_ERR, "%s: line %d: Invalid option or memory failure", filename, line);
+		return -1;
+	}
+
+	serv = (SERVER *) option->val;
+	if (serv == NULL) {
+		DEBUG(LOG_ERR, "option->val / server is NULL, allocating memory");
+		serv = malloc(sizeof(*serv));
+		if (serv == NULL) {
+			rc_log(LOG_CRIT, "read_config: out of memory");
+			free(p_dupe);
+			return -1;
+		}
+		memset(serv, 0, sizeof(*serv));
+		serv->max = 0;
+	}
+
+	p_pointer = strtok_r(p_dupe, ", \t", &p_save);
+
+	/* check to see for '[IPv6]:port' syntax */
+	if ((q = strchr(p_pointer,'[')) != NULL) {
+		*q = '\0';
+		q++;
+		p_pointer = q;
+
+		q = strchr(p_pointer, ']');
+		if (q == NULL) {
+			free(p_dupe);
+			rc_log(LOG_CRIT, "read_config: IPv6 parse error");
+			return -1;
+		}
+		*q = '\0';
+		q++;
+
+		if (q[0] == ':') {
+			q++;
+		}
+
+		/* Check to see if we have '[IPv6]:port:secret' syntax */
+		if((s=strchr(q, ':')) != NULL) {
+			*s = '\0';
+			s++;
+			serv->secret[serv->max] = strdup(s);
+			if (serv->secret[serv->max] == NULL) {
+				rc_log(LOG_CRIT, "read_config: out of memory");
+				if (option->val == NULL) {
+					free(p_dupe);
+					free(serv);
+				}
+				return -1;
+			}
+		}
+
+	} else /* Check to see if we have 'servername:port' syntax */
+	if ((q = strchr(p_pointer,':')) != NULL) {
+		*q = '\0';
+		q++;
+
+		/* Check to see if we have 'servername:port:secret' syntax */
+		if((s = strchr(q,':')) != NULL) {
+			*s = '\0';
+			s++;
+			serv->secret[serv->max] = strdup(s);
+			if (serv->secret[serv->max] == NULL) {
+				rc_log(LOG_CRIT, "read_config: out of memory");
+				if (option->val == NULL) {
+					free(p_dupe);
+					free(serv);
+				}
+				return -1;
+			}
+		}
+	}
+
+	if(q && strlen(q) > 0) {
+		serv->port[serv->max] = atoi(q);
+	} else {
+		if (!strcmp(option->name,"authserver"))
+			if ((svp = getservbyname ("radius", "udp")) == NULL)
+				serv->port[serv->max] = PW_AUTH_UDP_PORT;
+			else
+				serv->port[serv->max] = ntohs ((unsigned int) svp->s_port);
+		else if (!strcmp(option->name, "acctserver"))
+			if ((svp = getservbyname ("radacct", "udp")) == NULL)
+				serv->port[serv->max] = PW_ACCT_UDP_PORT;
+			else
+				serv->port[serv->max] = ntohs ((unsigned int) svp->s_port);
+		else {
+			rc_log(LOG_ERR, "%s: line %d: no default port for %s", filename, line, option->name);
+			if (option->val == NULL) {
+				free(p_dupe);
+				free(serv);
+			}
+			return -1;
+		}
+	}
+
+	serv->name[serv->max] = strdup(p_pointer);
+	if (serv->name[serv->max] == NULL) {
+		rc_log(LOG_CRIT, "read_config: out of memory");
+		if (option->val == NULL) {
+			free(p_dupe);
+			free(serv);
+		}
+		return -1;
+	}
+	free(p_dupe);
+
+	serv->deadtime_ends[serv->max] = -1;
+	serv->max++;
+
+	if (option->val == NULL)
+		option->val = (void *)serv;
+#endif
+	return 0;
+
+}
+
+static int set_option_auo(char const *filename, int line, OPTION *option, char const *p)
+{
+#if 0
+	int *iptr;
+	char *p_dupe = NULL;
+	char *p_pointer = NULL;
+	char *p_save = NULL;
+
+	p_dupe = strdup(p);
+
+	if (p_dupe == NULL) {
+		rc_log(LOG_WARNING, "%s: line %d: bogus option value", filename, line);
+		return -1;
+	}
+
+	if ((iptr = malloc(sizeof(iptr))) == NULL) {
+			rc_log(LOG_CRIT, "read_config: out of memory");
+			free(p_dupe);
+			return -1;
+	}
+
+	*iptr = 0;
+	p_pointer = strtok_r(p_dupe, ", \t", &p_save);
+
+	if (!strncmp(p_pointer, "local", 5))
+			*iptr = AUTH_LOCAL_FST;
+	else if (!strncmp(p_pointer, "radius", 6))
+			*iptr = AUTH_RADIUS_FST;
+	else {
+		rc_log(LOG_ERR,"%s: auth_order: unknown keyword: %s", filename, p);
+		free(iptr);
+		free(p_dupe);
+		return -1;
+	}
+
+	p_pointer = strtok_r(NULL, ", \t", &p_save);
+
+	if (p_pointer && (*p_pointer != '\0')) {
+		if ((*iptr & AUTH_RADIUS_FST) && !strcmp(p_pointer, "local"))
+			*iptr = (*iptr) | AUTH_LOCAL_SND;
+		else if ((*iptr & AUTH_LOCAL_FST) && !strcmp(p_pointer, "radius"))
+			*iptr = (*iptr) | AUTH_RADIUS_SND;
+		else {
+			rc_log(LOG_ERR,"%s: auth_order: unknown or unexpected keyword: %s", filename, p);
+			free(iptr);
+			free(p_dupe);
+			return -1;
+		}
+	}
+
+	option->val = (void *) iptr;
+
+	free(p_dupe);
+	return 0;
+#endif
+}
+
+/** Allow a config option to be added to rc_handle from inside a program
+ *
+ * @param rh a handle to parsed configuration.
+ * @param option_name the name of the option.
+ * @param option_val the value to be added.
+ * @param source typically should be %__FILE__ or %__func__ for logging purposes.
+ * @param line %__LINE__ for logging purposes.
+ * @return 0 on success, -1 on failure.
+ */
+int rc_add_config(rc_handle *rh, char const *option_name, char const *option_val, char const *source, int line)
+{
+	OPTION *option;
+
+	if ((option = find_option(rh, option_name, OT_ANY)) == NULL)
+	{
+		rc_log(LOG_ERR, "ERROR: unrecognized option: %s", option_name);
+		return -1;
+	}
+
+	if (option->status != ST_UNDEF)
+	{
+		rc_log(LOG_ERR, "ERROR: duplicate option: %s", option_name);
+		return -1;
+	}
+
+	switch (option->type) {
+		case OT_STR:
+			if (set_option_str(source, line, option, option_val) < 0) {
+				return -1;
+			}
+			break;
+		case OT_INT:
+			if (set_option_int(source, line, option, option_val) < 0) {
+				return -1;
+			}
+			break;
+		case OT_SRV:
+			if (set_option_srv(source, line, option, option_val) < 0) {
+				return -1;
+			}
+			break;
+		case OT_AUO:
+			if (set_option_auo(source, line, option, option_val) < 0) {
+				return -1;
+			}
+			break;
+		default:
+			rc_log(LOG_CRIT, "rc_add_config: impossible case branch!");
+			abort();
+	}
+
+	if (strcmp(option->name, "bindaddr") == 0) {
+		memset(&rh->own_bind_addr, 0, sizeof(rh->own_bind_addr));
+		rh->own_bind_addr_set = 0;
+		rc_own_bind_addr(rh, &rh->own_bind_addr);
+		rh->own_bind_addr_set = 1;
+	}
+
+	return 0;
+}
+
+/** Initialise a configuration structure
+ *
+ * Initialize the configuration structure from an external program.  For use when not
+ * running a standalone client that reads from a config file.
+ *
+ * @param rh a handle to parsed configuration.
+ * @return rc_handle on success, NULL on failure.
+ */
+rc_handle *rc_config_init(rc_handle *rh)
+{
+	int i;
+	SERVER *authservers;
+	SERVER *acctservers;
+	OPTION *acct;
+	OPTION *auth;
+
+        rh->config_options = malloc(sizeof(config_options_default));
+        if (rh->config_options == NULL)
+	{
+                rc_log(LOG_CRIT, "rc_config_init: out of memory");
+		rc_destroy(rh);
+                return NULL;
+        }
+        memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
+
+	acct = find_option(rh, "acctserver", OT_ANY);
+	auth = find_option(rh, "authserver", OT_ANY);
+	authservers = malloc(sizeof(SERVER));
+	acctservers = malloc(sizeof(SERVER));
+
+	if(authservers == NULL || acctservers == NULL)
+	{
+                rc_log(LOG_CRIT, "rc_config_init: error initializing server structs");
+		rc_destroy(rh);
+		if(authservers) free(authservers);
+		if(acctservers) free(acctservers);
+                return NULL;
+	}
+
+
+	authservers->max = 0;
+	acctservers->max = 0;
+
+	for(i=0; i < SERVER_MAX; i++)
+	{
+		authservers->name[i] = NULL;
+		authservers->secret[i] = NULL;
+		acctservers->name[i] = NULL;
+		acctservers->secret[i] = NULL;
+	}
+	acct->val = acctservers;
+	auth->val = authservers;
+	return rh;
+}
+
+/** Read the global config file
+ *
+ * @param filename a name of a file.
+ * @return new rc_handle on success, NULL when failure.
+ */
+void rc_read_config(rc_handle* rh)
+{
+    rh->config_options = &rcOptions;
+    
+    //memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
+}
+
+#if 0
+rc_handle *rc_read_config(char const *filename)
+{
+	FILE *configfd;
+	char buffer[512], *p;
+	OPTION *option;
+	int line;
+	size_t pos;
+	rc_handle *rh;
+
+	srandom((unsigned int)(time(NULL)+getpid()));
+
+	rh = rc_new();
+	if (rh == NULL)
+		return NULL;
+
+        rh->config_options = malloc(sizeof(config_options_default));
+        if (rh->config_options == NULL) {
+            rc_log(LOG_CRIT, "rc_read_config: out of memory");
+            rc_destroy(rh);
+            return NULL;
+        }
+        memcpy(rh->config_options, &config_options_default, sizeof(config_options_default));
+
+	if ((configfd = fopen(filename,"r")) == NULL)
+	{
+		rc_log(LOG_ERR,"rc_read_config: can't open %s: %s", filename, strerror(errno));
+		rc_destroy(rh);
+		return NULL;
+	}
+
+	line = 0;
+	while ((fgets(buffer, sizeof(buffer), configfd) != NULL))
+	{
+		line++;
+		p = buffer;
+
+		if ((*p == '\n') || (*p == '#') || (*p == '\0'))
+			continue;
+
+		p[strlen(p)-1] = '\0';
+
+
+		if ((pos = strcspn(p, "\t ")) == 0) {
+			rc_log(LOG_ERR, "%s: line %d: bogus format: %s", filename, line, p);
+			fclose(configfd);
+			rc_destroy(rh);
+			return NULL;
+		}
+
+		p[pos] = '\0';
+
+		if ((option = find_option(rh, p, OT_ANY)) == NULL) {
+			rc_log(LOG_ERR, "%s: line %d: unrecognized keyword: %s", filename, line, p);
+			fclose(configfd);
+			rc_destroy(rh);
+			return NULL;
+		}
+
+		if (option->status != ST_UNDEF) {
+			rc_log(LOG_ERR, "%s: line %d: duplicate option line: %s", filename, line, p);
+			fclose(configfd);
+			rc_destroy(rh);
+			return NULL;
+		}
+
+		p += pos+1;
+		while (isspace(*p))
+			p++;
+		pos = strlen(p) - 1;
+		while(pos != 0 && isspace(p[pos]))
+			pos--;
+		p[pos + 1] = '\0';
+
+		switch (option->type) {
+			case OT_STR:
+				if (set_option_str(filename, line, option, p) < 0) {
+					fclose(configfd);
+					rc_destroy(rh);
+				 	return NULL;
+				}
+				break;
+			case OT_INT:
+				if (set_option_int(filename, line, option, p) < 0) {
+					fclose(configfd);
+					rc_destroy(rh);
+				 	return NULL;
+				}
+				break;
+			case OT_SRV:
+				if (set_option_srv(filename, line, option, p) < 0) {
+					fclose(configfd);
+					rc_destroy(rh);
+				 	return NULL;
+				}
+				break;
+			case OT_AUO:
+				if (set_option_auo(filename, line, option, p) < 0) {
+					fclose(configfd);
+					rc_destroy(rh);
+				 	return NULL;
+				}
+				break;
+			default:
+				rc_log(LOG_CRIT, "rc_read_config: impossible case branch!");
+				abort();
+		}
+	}
+	fclose(configfd);
+
+	if (test_config(rh, filename) == -1) {
+		rc_destroy(rh);
+		return NULL;
+	}
+	return rh;
+}
+#endif
+
+/** Get the value of a config option
+ *
+ * @param rh a handle to parsed configuration.
+ * @param optname the name of an option.
+ * @return config option value.
+ */
+char *rc_conf_str(rc_handle const *rh, char const *optname)
+{
+	OPTION *option;
+
+	option = find_option(rh, optname, OT_STR);
+
+	if (option != NULL) {
+		return (char *)option->val;
+	} else {
+		rc_log(LOG_CRIT, "rc_conf_str: unkown config option requested: %s", optname);
+		return NULL;
+	}
+}
+
+/** Get the value of a config option
+ *
+ * @param rh a handle to parsed configuration.
+ * @param optname the name of an option.
+ * @return config option value.
+ */
+int rc_conf_int(rc_handle const *rh, char const *optname)
+{
+	OPTION *option;
+
+	option = find_option(rh, optname, OT_INT|OT_AUO);
+
+	if (option != NULL) {
+		if (option->val) {
+			return *((int *)option->val);
+		} else {
+			rc_log(LOG_ERR, "rc_conf_int: config option %s was not set", optname);
+			return 0;
+		}
+	} else {
+		rc_log(LOG_CRIT, "rc_conf_int: unkown config option requested: %s", optname);
+		return 0;
+	}
+}
+
+/** Get the value of a config option
+ *
+ * @param rh a handle to parsed configuration.
+ * @param optname the name of an option.
+ * @return config option value.
+ */
+SERVER *rc_conf_srv(rc_handle const *rh, char const *optname)
+{
+	OPTION *option;
+
+	option = find_option(rh, optname, OT_SRV);
+
+	if (option != NULL) {
+		return (SERVER *)option->val;
+	} else {
+		rc_log(LOG_CRIT, "rc_conf_srv: unkown config option requested: %s", optname);
+		return NULL;
+	}
+}
+
+/** Tests the configuration the user supplied
+ *
+ * @param rh a handle to parsed configuration.
+ * @param filename a name of a configuration file.
+ * @return 0 on success, -1 when failure.
+ */
+int test_config(rc_handle const *rh, char const *filename)
+{
+	SERVER *srv;
+
+	srv = rc_conf_srv(rh, "authserver");
+	if (!srv || !srv->max)
+	{
+		rc_log(LOG_ERR,"%s: no authserver specified", filename);
+		return -1;
+	}
+
+	srv = rc_conf_srv(rh, "acctserver");
+	if (!srv || !srv->max)
+	{
+		rc_log(LOG_ERR,"%s: no acctserver specified", filename);
+		return -1;
+	}
+	if (!rc_conf_str(rh, "servers"))
+	{
+		rc_log(LOG_ERR,"%s: no servers file specified", filename);
+		return -1;
+	}
+	if (!rc_conf_str(rh, "dictionary"))
+	{
+		rc_log(LOG_ERR,"%s: no dictionary specified", filename);
+		return -1;
+	}
+
+	if (rc_conf_int(rh, "radius_timeout") <= 0)
+	{
+		rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename);
+		return -1;
+	}
+	if (rc_conf_int(rh, "radius_retries") <= 0)
+	{
+		rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename);
+		return -1;
+	}
+	if (rc_conf_int(rh, "radius_deadtime") < 0)
+	{
+		rc_log(LOG_ERR,"%s: radius_deadtime is illegal", filename);
+		return -1;
+	}
+	if (rc_conf_int(rh, "login_tries") <= 0)
+	{
+		rc_log(LOG_ERR,"%s: login_tries <= 0 is illegal", filename);
+		return -1;
+	}
+	if (rc_conf_int(rh, "login_timeout") <= 0)
+	{
+		rc_log(LOG_ERR,"%s: login_timeout <= 0 is illegal", filename);
+		return -1;
+	}
+	if (rc_conf_str(rh, "mapfile") == NULL)
+	{
+		rc_log(LOG_ERR,"%s: mapfile not specified", filename);
+		return -1;
+	}
+	if (rc_conf_str(rh, "nologin") == NULL)
+	{
+		rc_log(LOG_ERR,"%s: nologin not specified", filename);
+		return -1;
+	}
+
+	return 0;
+}
+
+/** See if info matches hostname
+ *
+ * @param info a struct addrinfo
+ * @param hostname the name of the host.
+ * @return 0 on success, -1 when failure.
+ */
+static int find_match (const struct addrinfo* addr, const struct addrinfo *hostname)
+{
+#if 0  
+	const struct addrinfo *ptr, *ptr2;
+	unsigned len1, len2;
+
+	ptr = addr;
+	while(ptr) {
+		ptr2 = hostname;
+		while(ptr2) {
+			len1 = SA_GET_INLEN(ptr->ai_addr);
+			len2 = SA_GET_INLEN(ptr2->ai_addr);
+
+			if (len1 > 0 && 
+			    len1 == len2 && 
+			    memcmp(SA_GET_INADDR(ptr->ai_addr), SA_GET_INADDR(ptr2->ai_addr), len1) == 0) {
+				return 0;
+			}
+			ptr2 = ptr2->ai_next;
+ 		}
+		ptr = ptr->ai_next;
+ 	}
+#endif    
+ 	return -1;
+}
+
+/** Checks if provided address is local address
+ *
+ * @param addr an %AF_INET or %AF_INET6 address
+ * @return 0 if local, 1 if not local, -1 on failure.
+ */
+static int rc_ipaddr_local(const struct sockaddr *addr)
+{
+#if 0  
+	int temp_sock, res, serrno;
+	struct sockaddr tmpaddr;
+
+	memcpy(&tmpaddr, addr, SA_LEN(addr));
+
+	temp_sock = socket(addr->sa_family, SOCK_DGRAM, 0);
+	if (temp_sock == -1)
+		return -1;
+
+	if (addr->sa_family == AF_INET) {
+		((struct sockaddr_in*)&tmpaddr)->sin_port = 0;
+	} else {
+		((struct sockaddr_in6*)&tmpaddr)->sin6_port = 0;
+	}
+	res = bind(temp_sock, &tmpaddr, SA_LEN(&tmpaddr));
+	serrno = errno;
+	close(temp_sock);
+	if (res == 0)
+		return 0;
+	if (serrno == EADDRNOTAVAIL)
+		return 1;
+#endif    
+	return -1;
+}
+
+/** Checks if provided name refers to ourselves
+ *
+ * @param info an addrinfo of the host to check
+ * @return 0 if yes, 1 if no and -1 on failure.
+ */
+static int rc_is_myname(const struct addrinfo *info)
+{
+#if 0  
+	const struct addrinfo *p;
+	int	res;
+
+	p = info;
+	while(p != NULL) {
+		res = rc_ipaddr_local(p->ai_addr);
+		if (res == 0 || res == -1) {
+ 			return res;
+		}
+		p = p->ai_next;
+ 	}
+#endif    
+ 	return 1;
+}
+
+/** Locate a server in the rh config or if not found, check for a servers file
+ *
+ * @param rh a handle to parsed configuration.
+ * @param server_name the name of the server.
+ * @param info: will hold a pointer to addrinfo
+ * @param secret will hold the server's secret (of %MAX_SECRET_LENGTH).
+ * @param flags %AUTH or %ACCT
+ 
+ * @return 0 on success, -1 on failure.
+ */
+//int rc_find_server_addr(rc_handle const *, char const *, struct addrinfo **, char *, unsigned flags);
+
+int rc_find_server_addr(rc_handle const *rh, char const *server_name,
+                        struct addrinfo** info, char *secret, unsigned flags)
+{
+#if 0
+	int		i;
+	int             result = 0;
+	FILE           *clientfd;
+	char           *h;
+	char           *s;
+	char            buffer[128];
+	char            hostnm[AUTH_ID_LEN + 1];
+	char	       *buffer_save;
+	char	       *hostnm_save;
+	SERVER	       *authservers;
+	SERVER	       *acctservers;
+	struct addrinfo *tmpinfo = NULL;
+
+	/* Lookup the IP address of the radius server */
+	if ((*info = rc_getaddrinfo (server_name, flags==AUTH?PW_AI_AUTH:PW_AI_ACCT)) == NULL)
+		return -1;
+
+	if (flags == AUTH) {
+		/* Check to see if the server secret is defined in the rh config */
+		if( (authservers = rc_conf_srv(rh, "authserver")) != NULL )
+		{
+			for( i = 0; i < authservers->max; i++ )
+			{
+				if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) &&
+				    (authservers->secret[i] != NULL) )
+				{
+					memset (secret, '\0', MAX_SECRET_LENGTH);
+					strlcpy (secret, authservers->secret[i], MAX_SECRET_LENGTH);
+					return 0;
+				}
+			}
+		}
+	} else if (flags == ACCT) {
+		if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL )
+		{
+			for( i = 0; i < acctservers->max; i++ )
+			{
+				if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) &&
+				    (acctservers->secret[i] != NULL) )
+				{
+					memset (secret, '\0', MAX_SECRET_LENGTH);
+					strlcpy (secret, acctservers->secret[i], MAX_SECRET_LENGTH);
+					return 0;
+				}
+			}
+		}
+	}
+
+	/* We didn't find it in the rh_config or the servername is too long so look for a
+	 * servers file to define the secret(s)
+	 */
+
+	if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL)
+	{
+		rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers"));
+		goto fail;
+	}
+
+	while (fgets (buffer, sizeof (buffer), clientfd) != NULL)
+	{
+		if (*buffer == '#')
+			continue;
+
+		if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */
+			continue;
+
+		strlcpy (hostnm, h, AUTH_ID_LEN);
+
+		if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */
+			continue;
+
+		strlcpy (secret, s, MAX_SECRET_LENGTH);
+
+		if (!strchr (hostnm, '/')) /* If single name form */
+		{
+			tmpinfo = rc_getaddrinfo(hostnm, 0);
+			if (tmpinfo)
+			{
+				result = find_match (*info, tmpinfo);
+				if (result == 0)
+				{
+					result++;
+					break;
+				}
+
+				//freeaddrinfo(tmpinfo);
+				tmpinfo = NULL;
+			}
+		}
+		else /* <name1>/<name2> "paired" form */
+		{
+			strtok_r(hostnm, "/", &hostnm_save);
+			tmpinfo = rc_getaddrinfo(hostnm, 0);
+			if (tmpinfo)
+			{
+				if (rc_is_myname(tmpinfo) == 0)
+				{	     /* If we're the 1st name, target is 2nd */
+					if (find_match (*info, tmpinfo) == 0)
+					{
+						result++;
+						break;
+					}
+				}
+				else	/* If we were 2nd name, target is 1st name */
+				{
+					if (find_match (*info, tmpinfo) == 0)
+					{
+						result++;
+						break;
+					}
+				}
+				//freeaddrinfo(tmpinfo);
+				tmpinfo = NULL;
+			}
+		}
+	}
+	fclose (clientfd);
+	if (result == 0)
+	{
+		memset (buffer, '\0', sizeof (buffer));
+		memset (secret, '\0', MAX_SECRET_LENGTH);
+		rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s",
+			 server_name, rc_conf_str(rh, "servers"));
+		goto fail;
+	}
+	
+	result = 0;
+	goto cleanup;
+
+ fail:
+ 	//freeaddrinfo(*info);
+ 	result = -1;
+
+ cleanup:
+ 	//if (tmpinfo)
+ 		//freeaddrinfo(tmpinfo);
+
+	return result;
+#endif
+}
+
+/**
+ * rc_config_free:
+ * @param rh a handle to parsed configuration
+ *
+ * Free allocated config values
+ *
+ */
+
+void
+rc_config_free(rc_handle *rh)
+{
+	int i, j;
+	SERVER *serv;
+
+	if (rh->config_options == NULL)
+		return;
+
+	for (i = 0; i < NUM_OPTIONS; i++) {
+		if (rh->config_options[i].val == NULL)
+			continue;
+		if (rh->config_options[i].type == OT_SRV) {
+		        serv = (SERVER *)rh->config_options[i].val;
+			for (j = 0; j < serv->max; j++){
+				free(serv->name[j]);
+				if(serv->secret[j]) free(serv->secret[j]);
+			}
+			free(serv);
+		} else {
+			free(rh->config_options[i].val);
+		}
+	}
+	free(rh->config_options);
+	rh->config_options = NULL;
+}

+ 504 - 0
thirdparty/FreeRadius/lib/dict.c

@@ -0,0 +1,504 @@
+/*
+ * $Id: dict.c,v 1.10 2007/07/11 17:29:29 cparker Exp $
+ *
+ * Copyright (C) 1995,1996,1997 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#if defined ( __GNUC__ )
+#include <my_strings.h>
+#endif
+
+/** Initialize the dictionary
+ *
+ * Read all ATTRIBUTES into the dictionary_attributes list.
+ * Read all VALUES into the dictionary_values list.
+ *
+ * @param rh a handle to parsed configuration.
+ * @param filename the name of the dictionary file.
+ * @return 0 on success, -1 on failure.
+ */
+int rc_read_dictionary (rc_handle *rh, char const *filename)
+{
+	FILE           *dictfd;
+	char            dummystr[AUTH_ID_LEN];
+	char            namestr[AUTH_ID_LEN];
+	char            valstr[AUTH_ID_LEN];
+	char            attrstr[AUTH_ID_LEN];
+	char            typestr[AUTH_ID_LEN];
+	char		optstr[AUTH_ID_LEN];
+	char		*cp, *ifilename;
+	int             line_no;
+	DICT_ATTR      *attr;
+	DICT_VALUE     *dval;
+	DICT_VENDOR    *dvend;
+	char            buffer[256];
+	int             value;
+	int             type;
+	unsigned attr_vendorspec = 0;
+
+	if ((dictfd = fopen (filename, "r")) == NULL)
+	{
+		rc_log(LOG_ERR, "rc_read_dictionary couldn't open dictionary %s: %s",
+				filename, strerror(errno));
+		return -1;
+	}
+
+	line_no = 0;
+	while (fgets (buffer, sizeof (buffer), dictfd) != NULL)
+	{
+		line_no++;
+
+		/* Skip empty space */
+		if (*buffer == '#' || *buffer == '\0' || *buffer == '\n' || \
+		    *buffer == '\r')
+		{
+			continue;
+		}
+
+		/* Strip out comments */
+		cp = strchr(buffer, '#');
+		if (cp != NULL)
+		{
+			*cp = '\0';
+		}
+
+		if (strncmp (buffer, "ATTRIBUTE", 9) == 0)
+		{
+			optstr[0] = '\0';
+			/* Read the ATTRIBUTE line */
+			if (sscanf (buffer, "%63s%63s%63s%63s%63s", dummystr, namestr,
+				    valstr, typestr, optstr) < 4)
+			{
+				rc_log(LOG_ERR, "rc_read_dictionary: invalid attribute on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			/*
+			 * Validate all entries
+			 */
+			if (strlen (namestr) > NAME_LENGTH)
+			{
+				rc_log(LOG_ERR, "rc_read_dictionary: invalid name length on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			if (!isdigit (*valstr))
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid value on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+			value = atoi (valstr);
+
+			if (strcmp (typestr, "string") == 0)
+			{
+				type = PW_TYPE_STRING;
+			}
+			else if (strcmp (typestr, "integer") == 0)
+			{
+				type = PW_TYPE_INTEGER;
+			}
+			else if (strcmp (typestr, "ipaddr") == 0)
+			{
+				type = PW_TYPE_IPADDR;
+			}
+			else if (strcmp (typestr, "ipv6addr") == 0)
+			{
+				type = PW_TYPE_IPV6ADDR;
+			}
+			else if (strcmp (typestr, "ipv6prefix") == 0)
+			{
+				type = PW_TYPE_IPV6PREFIX;
+			}
+			else if (strcmp (typestr, "date") == 0)
+			{
+				type = PW_TYPE_DATE;
+			}
+			else
+			{
+				rc_log(LOG_ERR,
+				  "rc_read_dictionary: invalid type on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			dvend = NULL;
+			if (optstr[0] != '\0') {
+				char *cp1;
+				for (cp1 = optstr; cp1 != NULL; cp1 = cp) {
+					cp = strchr(cp1, ',');
+					if (cp != NULL) {
+						*cp = '\0';
+						cp++;
+					}
+					if (strncmp(cp1, "vendor=", 7) == 0)
+						cp1 += 7;
+					dvend = rc_dict_findvend(rh, cp1);
+					if (dvend == NULL) {
+						rc_log(LOG_ERR,
+						 "rc_read_dictionary: unknown Vendor-Id %s on line %d of dictionary %s",
+							 cp1, line_no, filename);
+						fclose(dictfd);
+						return -1;
+					}
+				}
+			}
+
+			/* Create a new attribute for the list */
+			if ((attr = malloc (sizeof (DICT_ATTR))) == NULL)
+			{
+				rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
+				fclose(dictfd);
+				return -1;
+			}
+			strcpy (attr->name, namestr);
+			attr->value = value | (attr_vendorspec << 16);
+			attr->type = type;
+
+			if (dvend != NULL) {
+				attr->value = value | (dvend->vendorpec << 16);
+			} else {
+				attr->value = value | (attr_vendorspec << 16);
+			}
+
+			/* Insert it into the list */
+			attr->next = rh->dictionary_attributes;
+			rh->dictionary_attributes = attr;
+		}
+		else if (strncmp (buffer, "VALUE", 5) == 0)
+		{
+			/* Read the VALUE line */
+			if (sscanf (buffer, "%63s%63s%63s%63s", dummystr, attrstr,
+				    namestr, valstr) != 4)
+			{
+				rc_log(LOG_ERR,
+			   "rc_read_dictionary: invalid value entry on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			/*
+			 * Validate all entries
+			 */
+			if (strlen (attrstr) > NAME_LENGTH)
+			{
+				rc_log(LOG_ERR,
+		      "rc_read_dictionary: invalid attribute length on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			if (strlen (namestr) > NAME_LENGTH)
+			{
+				rc_log(LOG_ERR,
+			   "rc_read_dictionary: invalid name length on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			if (!isdigit (*valstr))
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid value on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+			value = atoi (valstr);
+
+			/* Create a new VALUE entry for the list */
+			if ((dval = malloc (sizeof (DICT_VALUE))) == NULL)
+			{
+				rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
+				fclose(dictfd);
+				return -1;
+			}
+			strcpy (dval->attrname, attrstr);
+			strcpy (dval->name, namestr);
+			dval->value = value;
+
+			/* Insert it into the list */
+			dval->next = rh->dictionary_values;
+			rh->dictionary_values = dval;
+		}
+                else if (strncmp (buffer, "$INCLUDE", 8) == 0)
+                {
+			/* Read the $INCLUDE line */
+			if (sscanf (buffer, "%63s%63s", dummystr, namestr) != 2)
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid include entry on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+			ifilename = namestr;
+			/* Append directory if necessary */
+			if (namestr[0] != '/') {
+				cp = strrchr(filename, '/');
+				if (cp != NULL) {
+					ifilename = malloc(AUTH_ID_LEN);
+					*cp = '\0';
+					snprintf(ifilename, AUTH_ID_LEN, "%s/%s", filename, namestr);
+					*cp = '/';
+				}
+			}
+			if (rc_read_dictionary(rh, ifilename) < 0)
+			{
+				fclose(dictfd);
+				return -1;
+			}
+		}
+		else if (strncmp (buffer, "END-VENDOR", 10) == 0)
+		{
+			attr_vendorspec = 0;
+		}
+		else if (strncmp (buffer, "BEGIN-VENDOR", 12) == 0)
+		{
+			DICT_VENDOR *v;
+			/* Read the vendor name */
+			if (sscanf (buffer+12, "%63s", dummystr) != 1)
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			v = rc_dict_findvend(rh, dummystr);
+			if (v == NULL) {
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: unknown Vendor %s on line %d of dictionary %s",
+					 dummystr, line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			attr_vendorspec = v->vendorpec;
+		}
+		else if (strncmp (buffer, "VENDOR", 6) == 0)
+		{
+			/* Read the VALUE line */
+			if (sscanf (buffer, "%63s%63s%63s", dummystr, attrstr, valstr) != 3)
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			/* Validate all entries */
+			if (strlen (attrstr) > NAME_LENGTH)
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid attribute length on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+
+			if (!isdigit (*valstr))
+			{
+				rc_log(LOG_ERR,
+				 "rc_read_dictionary: invalid Vendor-Id on line %d of dictionary %s",
+					 line_no, filename);
+				fclose(dictfd);
+				return -1;
+			}
+			value = atoi (valstr);
+
+			/* Create a new VENDOR entry for the list */
+			dvend = malloc(sizeof(DICT_VENDOR));
+			if (dvend == NULL)
+			{
+				rc_log(LOG_CRIT, "rc_read_dictionary: out of memory");
+				fclose(dictfd);
+				return -1;
+			}
+			strcpy (dvend->vendorname, attrstr);
+			dvend->vendorpec = value;
+
+			/* Insert it into the list */
+			dvend->next = rh->dictionary_vendors;
+			rh->dictionary_vendors = dvend;
+                }
+	}
+	fclose (dictfd);
+	return 0;
+}
+
+/** Lookup a DICT_ATTR by attribute number
+ *
+ * @param rh a handle to parsed configuration.
+ * @param attribute the attribute ID.
+ * @return the full attribute structure based on the attribute id number.
+ */
+DICT_ATTR *rc_dict_getattr(rc_handle const *rh, int attribute)
+{
+	DICT_ATTR      *attr;
+
+	attr = rh->dictionary_attributes;
+	while (attr != NULL)
+	{
+		if (attr->value == attribute)
+		{
+			return attr;
+		}
+		attr = attr->next;
+	}
+	return NULL;
+}
+
+/** Lookup a DICT_ATTR by its name
+ *
+ * @param rh a handle to parsed configuration.
+ * @param attrname the attribute name.
+ *
+ * @return the full attribute structure based on the attribute name.
+ */
+DICT_ATTR *rc_dict_findattr(rc_handle const *rh, char const *attrname)
+{
+	DICT_ATTR      *attr;
+
+	attr = rh->dictionary_attributes;
+	while (attr != NULL)
+	{
+		if (strcasecmp (attr->name, attrname) == 0)
+		{
+			return attr;
+		}
+		attr = attr->next;
+	}
+	return NULL;
+}
+
+
+/** Lookup a DICT_VALUE by its name
+ *
+ * @param rh a handle to parsed configuration.
+ * @param valname the value name.
+ * @return the full value structure based on the value name.
+ */
+DICT_VALUE *rc_dict_findval(rc_handle const *rh, char const *valname)
+{
+	DICT_VALUE     *val;
+
+	val = rh->dictionary_values;
+	while (val != NULL)
+	{
+		if (strcasecmp (val->name, valname) == 0)
+		{
+			return val;
+		}
+		val = val->next;
+	}
+	return NULL;
+}
+
+/** Lookup a DICT_VENDOR by its name
+ *
+ * @param rh a handle to parsed configuration.
+ * @param valname the vendor name.
+ * @return the full vendor structure based on the vendor name.
+ */
+DICT_VENDOR *rc_dict_findvend(rc_handle const *rh, char const *vendorname)
+{
+	DICT_VENDOR	*vend;
+
+	for (vend = rh->dictionary_vendors; vend != NULL; vend = vend->next)
+		if (strcasecmp(vend->vendorname, vendorname) == 0)
+			return vend;
+	return NULL;
+}
+
+/** Lookup a DICT_VENDOR by its IANA number
+ *
+ * @param rh a handle to parsed configuration.
+ * @param vendorpec the vendor ID.
+ * @return the full vendor structure based on the vendor id number.
+ */
+DICT_VENDOR *rc_dict_getvend (rc_handle const *rh, int vendorpec)
+{
+        DICT_VENDOR      *vend;
+
+	for (vend = rh->dictionary_vendors; vend != NULL; vend = vend->next)
+		if (vend->vendorpec == vendorpec)
+			return vend;
+	return NULL;
+}
+
+/** Get DICT_VALUE based on attribute name and integer value number
+ *
+ * @param rh a handle to parsed configuration.
+ * @param value the attribute value.
+ * @param attrname the attribute name.
+ * @return the full value structure based on the actual value and the associated attribute name.
+ */
+DICT_VALUE *rc_dict_getval(rc_handle const *rh, uint32_t value, char const *attrname)
+{
+	DICT_VALUE     *val;
+
+	val = rh->dictionary_values;
+	while (val != NULL)
+	{
+		if (strcmp (val->attrname, attrname) == 0 &&
+				val->value == value)
+		{
+			return val;
+		}
+		val = val->next;
+	}
+	return NULL;
+}
+
+/** Frees the allocated av lists
+ *
+ * @param rh a handle to parsed configuration.
+ */
+void rc_dict_free(rc_handle *rh)
+{
+	DICT_ATTR	*attr, *nattr;
+	DICT_VALUE	*val, *nval;
+	DICT_VENDOR	*vend, *nvend;
+
+	for (attr = rh->dictionary_attributes; attr != NULL; attr = nattr) {
+		nattr = attr->next;
+		free(attr);
+	}
+	for (val = rh->dictionary_values; val != NULL; val = nval) {
+		nval = val->next;
+		free(val);
+	}
+	for (vend = rh->dictionary_vendors; vend != NULL; vend = nvend) {
+		nvend = vend->next;
+		free(vend);
+	}
+	rh->dictionary_attributes = NULL;
+	rh->dictionary_values = NULL;
+	rh->dictionary_vendors = NULL;
+}

+ 49 - 0
thirdparty/FreeRadius/lib/fr_log.c

@@ -0,0 +1,49 @@
+/*
+ * $Id: log.c,v 1.5 2007/06/21 18:07:23 cparker Exp $
+ *
+ * Copyright (C) 1995,1996,1997 Lars Fenneberg
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+
+/** Opens system log
+ *
+ * @param ident the name of the program.
+ */
+void rc_openlog(char const *ident)
+{
+#ifndef _MSC_VER /* TODO: Fix me */
+//	openlog(ident, LOG_PID, RC_LOG_FACILITY);
+#endif
+}
+
+/** Logs information on system log
+ *
+ * @param prio the syslog priority.
+ * @param format the format of the data to print.
+ */
+void rc_log(int prio, char const *format, ...)
+{
+#ifdef RC_LOG  
+    printf(format);
+#endif    
+/*  
+	char buff[1024];
+	va_list ap;
+
+	va_start(ap,format);
+	vsnprintf(buff, sizeof(buff), format, ap);
+	va_end(ap);
+
+#ifndef _MSC_VER  TODO: Fix me 
+	syslog(prio, "%s", buff);
+#endif
+*/    
+}

+ 251 - 0
thirdparty/FreeRadius/lib/fr_md5.c

@@ -0,0 +1,251 @@
+#include "fr_md5.h"
+
+/*	The below was retrieved from
+ *	http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.c?rev=1.1
+ *	with the following changes:
+ *	#includes commented out.
+ *	Support context->count as uint32_t[2] instead of uint64_t
+ *	u_int* to uint*
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.	This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/*#include <sys/param.h>*/
+/*#include <sys/systm.h>*/
+/*#include <crypto/md5.h>*/
+
+#define PUT_64BIT_LE(cp, value) do {				\
+	(cp)[7] = (value)[1] >> 24;					\
+	(cp)[6] = (value)[1] >> 16;					\
+	(cp)[5] = (value)[1] >> 8;					\
+	(cp)[4] = (value)[1];						\
+	(cp)[3] = (value)[0] >> 24;					\
+	(cp)[2] = (value)[0] >> 16;					\
+	(cp)[1] = (value)[0] >> 8;					\
+	(cp)[0] = (value)[0]; } while (0)
+
+#define PUT_32BIT_LE(cp, value) do {					\
+	(cp)[3] = (value) >> 24;					\
+	(cp)[2] = (value) >> 16;					\
+	(cp)[1] = (value) >> 8;						\
+	(cp)[0] = (value); } while (0)
+
+static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(MD5_CTX *ctx)
+{
+	ctx->count[0] = 0;
+	ctx->count[1] = 0;
+	ctx->state[0] = 0x67452301;
+	ctx->state[1] = 0xefcdab89;
+	ctx->state[2] = 0x98badcfe;
+	ctx->state[3] = 0x10325476;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(MD5_CTX *ctx, uint8_t const *input, size_t len)
+{
+	size_t have, need;
+
+	/* Check how many bytes we already have and how many more we need. */
+	have = (size_t)((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
+	need = MD5_BLOCK_LENGTH - have;
+
+	/* Update bitcount */
+/*	ctx->count += (uint64_t)len << 3;*/
+	if ((ctx->count[0] += ((uint32_t)len << 3)) < (uint32_t)len) {
+	/* Overflowed ctx->count[0] */
+		ctx->count[1]++;
+	}
+	ctx->count[1] += ((uint32_t)len >> 29);
+
+
+
+	if (len >= need) {
+		if (have != 0) {
+			memcpy(ctx->buffer + have, input, need);
+			MD5Transform(ctx->state, ctx->buffer);
+			input += need;
+			len -= need;
+			have = 0;
+		}
+
+		/* Process data in MD5_BLOCK_LENGTH-byte chunks. */
+		while (len >= MD5_BLOCK_LENGTH) {
+			MD5Transform(ctx->state, input);
+			input += MD5_BLOCK_LENGTH;
+			len -= MD5_BLOCK_LENGTH;
+		}
+	}
+
+	/* Handle any remaining bytes of data. */
+	if (len != 0)
+		memcpy(ctx->buffer + have, input, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
+{
+	uint8_t count[8];
+	size_t padlen;
+	int i;
+
+	/* Convert count to 8 bytes in little endian order. */
+	PUT_64BIT_LE(count, ctx->count);
+
+	/* Pad out to 56 mod 64. */
+	padlen = MD5_BLOCK_LENGTH -
+	    ((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
+	if (padlen < 1 + 8)
+		padlen += MD5_BLOCK_LENGTH;
+	MD5Update(ctx, PADDING, padlen - 8);		/* padlen - 8 <= 64 */
+	MD5Update(ctx, count, 8);
+
+	if (digest != NULL) {
+		for (i = 0; i < 4; i++)
+			PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
+	}
+	memset(ctx, 0, sizeof(*ctx));	/* in case it's sensitive */
+}
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(uint32_t state[4], uint8_t const block[MD5_BLOCK_LENGTH])
+{
+	uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
+
+	for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
+		in[a] = (uint32_t)(
+		    (uint32_t)(block[a * 4 + 0]) |
+		    (uint32_t)(block[a * 4 + 1]) <<  8 |
+		    (uint32_t)(block[a * 4 + 2]) << 16 |
+		    (uint32_t)(block[a * 4 + 3]) << 24);
+	}
+
+	a = state[0];
+	b = state[1];
+	c = state[2];
+	d = state[3];
+
+	MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
+	MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
+	MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
+	MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
+	MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
+	MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
+	MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
+	MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
+	MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
+	MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
+	MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
+	MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
+	MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
+
+	state[0] += a;
+	state[1] += b;
+	state[2] += c;
+	state[3] += d;
+}

+ 86 - 0
thirdparty/FreeRadius/lib/fr_md5.h

@@ -0,0 +1,86 @@
+/*
+ * md5.h        Structures and prototypes for md5.
+ *
+ * Version:     $Id: md5.h,v 1.2 2007/06/21 18:07:24 cparker Exp $
+ * License:	BSD, but largely derived from a public domain source.
+ *
+ */
+
+#ifndef _RCRAD_MD5_H
+#define _RCRAD_MD5_H
+
+#include "radius_config.h"
+
+#ifdef HAVE_NETTLE
+
+#include <nettle/md5-compat.h>
+
+#else
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <string.h>
+/*
+ *  FreeRADIUS Client defines to ensure globally unique MD5 function names,
+ *  so that we don't pick up vendor-specific broken MD5 libraries.
+ */
+#define MD5_CTX		librad_MD5_CTX
+#define MD5Init		librad_MD5Init
+#define MD5Update	librad_MD5Update
+#define MD5Final	librad_MD5Final
+#define MD5Transform	librad_MD5Transform
+
+/*  The below was retrieved from
+ *  http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.h?rev=1.1
+ *  With the following changes: uint64_t => uint32_t[2]
+ *  Commented out #include <sys/cdefs.h>
+ *  Commented out the __BEGIN and __END _DECLS, and the __attributes.
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ */
+
+#define	MD5_BLOCK_LENGTH		64
+#define	MD5_DIGEST_LENGTH		16
+
+typedef struct MD5Context {
+	uint32_t state[4];			//!< State.
+	uint32_t count[2];			//!< Number of bits, mod 2^64.
+	uint8_t buffer[MD5_BLOCK_LENGTH];	//!< Input buffer.
+} MD5_CTX;
+
+/* include <sys/cdefs.h> */
+
+/* __BEGIN_DECLS */
+void	 MD5Init(MD5_CTX *);
+void	 MD5Update(MD5_CTX *, uint8_t const *, size_t)
+/*		__attribute__((__bounded__(__string__,2,3)))*/;
+void	 MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
+/*		__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)))*/;
+void	 MD5Transform(uint32_t [4], uint8_t const [MD5_BLOCK_LENGTH])
+/*		__attribute__((__bounded__(__minbytes__,1,4)))*/
+/*		__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)))*/;
+/* __END_DECLS */
+
+#endif /* HAVE_NETTLE */
+
+#endif /* _RCRAD_MD5_H */

+ 56 - 0
thirdparty/FreeRadius/lib/fr_options.h

@@ -0,0 +1,56 @@
+/*
+ * $Id: options.h,v 1.6 2008/03/05 16:35:20 cparker Exp $
+ *
+ * Copyright (C) 1996 Lars Fenneberg
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+#define OPTION_LEN	64
+
+/* ids for different option types */
+#define OT_STR		(1<<0)			//!< string.
+#define OT_INT		(1<<1)			//!< integer.
+#define OT_SRV		(1<<2)			//!< server list.
+#define OT_AUO		(1<<3)			//!< authentication order.
+
+#define OT_ANY		((unsigned int)~0)	//!< Used internally.
+
+/* status types */
+#define ST_UNDEF	(1<<0)			//!< option is undefined.
+
+typedef struct _option {
+	char name[OPTION_LEN];			//!< name of the option.
+	int type, status;			//!< type and status.
+	void *val;				//!< pointer to option value.
+} OPTION;
+
+static OPTION config_options_default[] = {
+/* internally used options */
+{"config_file",		OT_STR, ST_UNDEF, NULL},
+/* General options */
+{"auth_order",	 	OT_AUO, ST_UNDEF, NULL},
+{"login_tries",	 	OT_INT, ST_UNDEF, NULL},
+{"login_timeout",	OT_INT, ST_UNDEF, NULL},
+{"nologin",		OT_STR, ST_UNDEF, NULL},
+{"issue",		OT_STR, ST_UNDEF, NULL},
+/* RADIUS specific options */
+{"authserver",		OT_SRV, ST_UNDEF, NULL},
+{"acctserver",		OT_SRV, ST_UNDEF, NULL},
+{"servers",		OT_STR, ST_UNDEF, NULL},
+{"dictionary",		OT_STR, ST_UNDEF, NULL},
+{"login_radius",	OT_STR, ST_UNDEF, NULL},
+{"mapfile",		OT_STR, ST_UNDEF, NULL},
+{"default_realm",	OT_STR, ST_UNDEF, NULL},
+{"radius_timeout",	OT_INT, ST_UNDEF, NULL},
+{"radius_retries",	OT_INT,	ST_UNDEF, NULL},
+{"radius_deadtime",	OT_INT, ST_UNDEF, NULL},
+{"bindaddr",		OT_STR, ST_UNDEF, NULL},
+/* local options */
+{"login_local",		OT_STR, ST_UNDEF, NULL},
+};
+
+#define	NUM_OPTIONS	((sizeof(config_options_default))/(sizeof(config_options_default[0])))

+ 29 - 0
thirdparty/FreeRadius/lib/rc-md5.c

@@ -0,0 +1,29 @@
+/* MD5 message-digest algorithm */
+
+/* This file is licensed under the BSD License, but is largely derived from
+ * public domain source code
+ */
+
+/*
+ *  FORCE MD5 TO USE OUR MD5 HEADER FILE!
+ *
+ *  If we don't do this, it might pick up the systems broken MD5.
+ */
+#include "rc-md5.h"
+
+/** Hash the provided data using MD5
+ *
+ * @param[out] output will hold a 16-byte checksum.
+ * @param[in] input pointer to data to hash.
+ * @param[in] inlen the length of input.
+ */
+void rc_md5_calc(unsigned char *output, unsigned char const *input,
+		 size_t inlen)
+{
+	MD5_CTX	context;
+
+	MD5Init(&context);
+	MD5Update(&context, input, inlen);
+	MD5Final(output, &context);
+}
+

+ 28 - 0
thirdparty/FreeRadius/lib/rc-md5.h

@@ -0,0 +1,28 @@
+/*
+ * md5.h        Structures and prototypes for md5.
+ *
+ * Version:     $Id: md5.h,v 1.2 2007/06/21 18:07:24 cparker Exp $
+ * License:	BSD
+ *
+ */
+
+#ifndef _RC_MD5_H
+#define _RC_MD5_H
+
+#include "radius_config.h"
+#include <stdlib.h>
+
+#ifdef HAVE_NETTLE
+
+#include <nettle/md5-compat.h>
+
+#else
+
+#include "fr_md5.h"
+
+#endif /* HAVE_NETTLE */
+
+void rc_md5_calc(unsigned char *output, unsigned char const *input,
+		     size_t inputlen);
+
+#endif /* _RC_MD5_H */

+ 549 - 0
thirdparty/FreeRadius/lib/sendserver.c

@@ -0,0 +1,549 @@
+/*
+ * $Id: sendserver.c,v 1.30 2010/06/15 09:22:52 aland Exp $
+ *
+ * Copyright (C) 1995,1996,1997 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+//#include <poll.h>
+
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#include <pathnames.h>
+#include "freeradius-client.h"
+#include "util.h"
+#include "radius_user.h"
+#include "parameters.h"
+
+#include "lwip/sockets.h"
+
+#define	SA(p)	((struct sockaddr *)(p))
+
+static void rc_random_vector (unsigned char *);
+static int rc_check_reply (AUTH_HDR *, int, char const *, unsigned char const *, unsigned char);
+
+/** Packs an attribute value pair list into a buffer
+ *
+ * @param vp a pointer to a #VALUE_PAIR.
+ * @param secret the secret used by the server.
+ * @param auth a pointer to #AUTH_HDR.
+ * @return The number of octets packed.
+ */
+static int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth)
+{
+	int             length, i, pc, padded_length;
+	int             total_length = 0;
+	size_t			secretlen;
+	uint32_t           lvalue, vendor;
+	unsigned char   passbuf[MAX(AUTH_PASS_LEN, CHAP_VALUE_LENGTH)];
+	unsigned char   md5buf[256];
+	unsigned char   *buf, *vector, *vsa_length_ptr;
+
+	buf = auth->data;
+
+	while (vp != NULL)
+	{
+		vsa_length_ptr = NULL;
+		if (VENDOR(vp->attribute) != 0) {
+			*buf++ = PW_VENDOR_SPECIFIC;
+			vsa_length_ptr = buf;
+			*buf++ = 6;
+			vendor = htonl(VENDOR(vp->attribute));
+			memcpy(buf, &vendor, sizeof(uint32_t));
+			buf += 4;
+			total_length += 6;
+		}
+		*buf++ = (vp->attribute & 0xff);
+
+		switch (vp->attribute)
+		{
+		 case PW_USER_PASSWORD:
+
+		  /* Encrypt the password */
+
+		  /* Chop off password at AUTH_PASS_LEN */
+		  length = vp->lvalue;
+		  if (length > AUTH_PASS_LEN)
+			length = AUTH_PASS_LEN;
+
+		  /* Calculate the padded length */
+		  padded_length = (length+(AUTH_VECTOR_LEN-1)) & ~(AUTH_VECTOR_LEN-1);
+
+		  /* Record the attribute length */
+		  *buf++ = padded_length + 2;
+		  if (vsa_length_ptr != NULL) *vsa_length_ptr += padded_length + 2;
+
+		  /* Pad the password with zeros */
+		  memset ((char *) passbuf, '\0', AUTH_PASS_LEN);
+		  memcpy ((char *) passbuf, vp->strvalue, (size_t) length);
+
+		  secretlen = strlen (secret);
+		  vector = (unsigned char *)auth->vector;
+		  for(i = 0; i < padded_length; i += AUTH_VECTOR_LEN)
+		  {
+		  	/* Calculate the MD5 digest*/
+		  	strcpy ((char *) md5buf, secret);
+		  	memcpy ((char *) md5buf + secretlen, vector,
+		  		  AUTH_VECTOR_LEN);
+		  	rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN);
+
+		        /* Remeber the start of the digest */
+		  	vector = buf;
+
+			/* Xor the password into the MD5 digest */
+			for (pc = i; pc < (i + AUTH_VECTOR_LEN); pc++)
+		  	{
+				*buf++ ^= passbuf[pc];
+		  	}
+		  }
+
+		  total_length += padded_length + 2;
+
+		  break;
+		 default:
+		  switch (vp->type)
+		  {
+		    case PW_TYPE_STRING:
+			length = vp->lvalue;
+			*buf++ = length + 2;
+			if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
+			memcpy (buf, vp->strvalue, (size_t) length);
+			buf += length;
+			total_length += length + 2;
+			break;
+
+		    case PW_TYPE_IPV6ADDR:
+			length = 16;
+			*buf++ = length + 2;
+			if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
+			memcpy (buf, vp->strvalue, (size_t) length);
+			buf += length;
+			total_length += length + 2;
+			break;
+
+		    case PW_TYPE_IPV6PREFIX:
+			length = vp->lvalue;
+			*buf++ = length + 2;
+			if (vsa_length_ptr != NULL) *vsa_length_ptr += length + 2;
+			memcpy (buf, vp->strvalue, (size_t) length);
+			buf += length;
+			total_length += length + 2;
+			break;
+
+		    case PW_TYPE_INTEGER:
+		    case PW_TYPE_IPADDR:
+		    case PW_TYPE_DATE:
+			*buf++ = sizeof (uint32_t) + 2;
+			if (vsa_length_ptr != NULL) *vsa_length_ptr += sizeof(uint32_t) + 2;
+			lvalue = htonl (vp->lvalue);
+			memcpy (buf, (char *) &lvalue, sizeof (uint32_t));
+			buf += sizeof (uint32_t);
+			total_length += sizeof (uint32_t) + 2;
+			break;
+
+		    default:
+			break;
+		  }
+		  break;
+		}
+		vp = vp->next;
+	}
+	return total_length;
+}
+
+/** Appends a string to the provided buffer
+ *
+ * @param dest the destination buffer.
+ * @param max_size the maximum size available in the destination buffer.
+ * @param pos the current position in the dest buffer; initially must be zero.
+ * @param src the source buffer to append.
+ */
+static void strappend(char *dest, unsigned max_size, int *pos, const char *src)
+{
+	unsigned len = strlen(src) + 1;
+
+	if (*pos == -1)
+		return;
+
+	if (len + *pos > max_size) {
+		*pos = -1;
+		return;
+	}
+
+	memcpy(&dest[*pos], src, len);
+	*pos += len-1;
+	return;
+}
+
+/** Sends a request to a RADIUS server and waits for the reply
+ *
+ * @param rh a handle to parsed configuration
+ * @param data a pointer to a #SEND_DATA structure
+ * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of
+ *	any %PW_REPLY_MESSAGE received.
+ * @param flags must be %AUTH or %ACCT
+ * @return %OK_RC (0) on success, %TIMEOUT_RC on timeout %REJECT_RC on acess reject, or negative
+ *	on failure as return value.
+ */
+
+
+#define RECV_BUF_LEN    100
+static char recv_buffer[RECV_BUF_LEN];
+
+int rc_send_server (rc_handle *rh, SEND_DATA *data, char *msg, unsigned flags)
+{
+    struct sockaddr_in sa,ra;
+    int             socket;
+    fdsets          sets;
+    AUTH_HDR*       auth;
+    AUTH_HDR*       recv_auth;
+    unsigned char   vector[AUTH_VECTOR_LEN];
+    char            secret[MAX_SECRET_LENGTH + 1];
+    int             total_length;
+    int             sendLen, recvLen;
+    int             length;
+    int             pos;
+    uint8_t*        attr;
+    int             result = 0;
+    VALUE_PAIR*     vp;
+    
+    char            rcNetParams[20];
+    uint32_t        port;
+    uint8_t         tmpLen;
+    
+    initFdsets(&sets);
+    
+    memset(secret, 0, MAX_SECRET_LENGTH + 1);
+    GetRDSPasswordkStr(secret, &tmpLen);
+/*        
+	if(data->secret != NULL) {
+		//strlcpy(secret, data->secret, MAX_SECRET_LENGTH);
+		strlcpy(secret, "R04ekR4MP2", MAX_SECRET_LENGTH);
+    }
+*/
+    // Устанавливаем сетевые параметры
+    memset(rcNetParams, 0, 20);
+    GetRDSIpStr(rcNetParams, &tmpLen);
+        
+    // IP radius server
+    memset(&ra, 0, sizeof(struct sockaddr_in));
+    ra.sin_family = AF_INET;
+    ra.sin_addr.s_addr = inet_addr(rcNetParams);
+    
+    // port
+    memset(rcNetParams, 0, 20);
+    GetRDSPortStr(rcNetParams, &tmpLen);
+    port = atoi(rcNetParams);
+    ra.sin_port = htons(port);
+        
+    socket = socket(PF_INET, SOCK_DGRAM, 0);
+    if ( socket < 0 )
+    {
+        //printf("socket call failed");
+        return -1;
+    }
+        
+    // Build a request  (PW_ACCESS_REQUEST)
+    auth = (AUTH_HDR *) msg;
+	auth->code = data->code;
+	auth->id = data->seq_nbr;
+
+    rc_random_vector(vector);
+	memcpy((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
+
+	total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN;
+	auth->length = htons ((unsigned short) total_length);
+	        
+    // Bind socket
+    memset(rcNetParams, 0, 20);
+    GetIpStr(rcNetParams, &tmpLen);
+    
+    memset(&sa, 0, sizeof(struct sockaddr_in));
+    sa.sin_family = AF_INET;
+    sa.sin_addr.s_addr = inet_addr(rcNetParams);
+    sa.sin_port = htons(port);
+    
+    if (bind(socket, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1)
+    {
+        //printf("Bind to Port Number %d ,IP address %s failed\n", DEVICE_PORT_NUM, DEVICE_IP_ADDR);
+        close(socket);
+        return -1;
+    }
+       
+    sendLen = sendto(socket, (char*)auth, total_length, 0, (struct sockaddr*)&ra, sizeof(ra));
+    if(sendLen < 0)
+    {
+        //printf("send failed\n");
+        close(socket);
+        return NET_ERR_RC;
+    }
+   
+    // Подготовка буфера для приема
+    memset(recv_buffer, 0, RECV_BUF_LEN);
+    
+    // Получение ответа, select
+    if (!recvSelect(&sets, &socket, 2000)) {
+        //printf("SOCK recv timeout!\r\n");
+        close(socket);
+        return NET_ERR_RC;
+    }
+    
+    // Данные можно принимать
+    socklen_t sl = sizeof(sa);
+    recvLen = recvfrom(socket, recv_buffer, RECV_BUF_LEN, 0, (struct sockaddr*)&ra, &sl);
+
+    recv_auth = (AUTH_HDR*)recv_buffer;
+    
+    // Проверки размера входящего сообщения
+    if (recvLen < AUTH_HDR_LEN || recvLen < ntohs(recv_auth->length)) {
+		//printf("radius_server: reply is too short\r\n");
+		close(socket);
+        return NET_ERR_RC;
+	}
+    
+    if (recvLen > ntohs(recv_auth->length)) 
+    {
+        recvLen = ntohs(recv_auth->length);
+    }
+    
+    // Verify that it's a valid RADIUS packet before doing ANYTHING with it.
+	attr = recv_buffer + AUTH_HDR_LEN;
+	while (attr < (recv_buffer + recvLen)) {
+		if (attr[0] == 0) {
+            //printf("radius_server: attribute zero is invalid\r\n");
+            close(socket);
+            return NET_ERR_RC;
+		}
+
+		if (attr[1] < 2) {
+            //printf("radius_server: attribute length is too small\r\n");
+            close(socket);
+            return NET_ERR_RC;
+		}
+
+		if ((attr + attr[1]) > (recv_buffer + recvLen)) {
+            //printf("radius_server: attribute overflows the packet\r\n");
+            close(socket);
+            return NET_ERR_RC;
+		}
+
+		attr += attr[1];
+	}
+    
+    
+    result = rc_check_reply(recv_auth, RECV_BUF_LEN, secret, vector, data->seq_nbr);
+    
+    length = ntohs(recv_auth->length)  - AUTH_HDR_LEN;
+	if (length > 0) {
+		data->receive_pairs = rc_avpair_gen(rh, NULL, recv_auth->data, length, 0);
+	} else {
+		data->receive_pairs = NULL;
+	}
+
+	if (result != OK_RC) {
+		return result;
+	}
+    
+    if (msg) {
+		*msg = '\0';
+		pos = 0;
+		vp = data->receive_pairs;
+		while (vp)
+		{
+			if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE, 0)))
+			{
+				strappend(msg, PW_MAX_MSG_SIZE, &pos, vp->strvalue);
+				strappend(msg, PW_MAX_MSG_SIZE, &pos, "\n");
+				vp = vp->next;
+			}
+		}
+	}
+
+	if ((recv_auth->code == PW_ACCESS_ACCEPT) ||
+		(recv_auth->code == PW_PASSWORD_ACK) ||
+		(recv_auth->code == PW_ACCOUNTING_RESPONSE))
+	{
+        result = RC_GetAccessRights(recv_buffer);
+	}
+	else if ((recv_auth->code == PW_ACCESS_REJECT) ||
+		(recv_auth->code == PW_PASSWORD_REJECT))
+	{
+		result = REJECT_RC;
+	}
+	else
+	{
+		rc_log(LOG_ERR, "rc_send_server: received RADIUS server response neither ACCEPT nor REJECT, invalid");
+		result = BADRESP_RC;
+	}
+    
+    //printf("\r\nRadius server end communication\r\n");
+    close(socket);
+    return result;
+}
+
+/** Verify items in returned packet
+ *
+ * @param auth a pointer to #AUTH_HDR.
+ * @param bufferlen the available buffer length.
+ * @param secret the secret used by the server.
+ * @param vector a random vector of %AUTH_VECTOR_LEN.
+ * @param seq_nbr a unique sequence number.
+ * @return %OK_RC upon success, %BADRESP_RC if anything looks funny.
+ */
+static int rc_check_reply (AUTH_HDR *auth, int bufferlen, char const *secret, unsigned char const *vector, uint8_t seq_nbr)
+{
+	int             secretlen;
+	int             totallen;
+	unsigned char   calc_digest[AUTH_VECTOR_LEN];
+	unsigned char   reply_digest[AUTH_VECTOR_LEN];
+#ifdef DIGEST_DEBUG
+	uint8_t		*ptr;
+#endif
+
+	totallen = ntohs (auth->length);
+	secretlen = (int)strlen (secret);
+
+	/* Do sanity checks on packet length */
+	if ((totallen < 20) || (totallen > 4096))
+	{
+		rc_log(LOG_ERR, "rc_check_reply: received RADIUS server response with invalid length");
+		return BADRESP_RC;
+	}
+
+	/* Verify buffer space, should never trigger with current buffer size and check above */
+	if ((totallen + secretlen) > bufferlen)
+	{
+		rc_log(LOG_ERR, "rc_check_reply: not enough buffer space to verify RADIUS server response");
+		return BADRESP_RC;
+	}
+
+	/* Verify that id (seq. number) matches what we sent */
+	if (auth->id != seq_nbr)
+	{
+		rc_log(LOG_ERR, "rc_check_reply: received non-matching id in RADIUS server response");
+		return BADRESP_RC;
+	}
+
+	/* Verify the reply digest */
+	memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN);
+	memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
+	memcpy ((char *) auth + totallen, secret, secretlen);
+#ifdef DIGEST_DEBUG
+        rc_log(LOG_ERR, "Calculating digest on:");
+        for (ptr = (u_char *)auth; ptr < ((u_char *)auth) + totallen + secretlen; ptr += 32) {
+                char buf[65];
+                int i;
+
+                buf[0] = '\0';
+                for (i = 0; i < 32; i++) {
+                        if (ptr + i >= ((u_char *)auth) + totallen + secretlen)
+                                break;
+                        sprintf(buf + i * 2, "%.2X", ptr[i]);
+                }
+                rc_log(LOG_ERR, "  %s", buf);
+        }
+#endif
+	rc_md5_calc (calc_digest, (unsigned char *) auth, totallen + secretlen);
+#ifdef DIGEST_DEBUG
+	rc_log(LOG_ERR, "Calculated digest is:");
+        for (ptr = (u_char *)calc_digest; ptr < ((u_char *)calc_digest) + 16; ptr += 32) {
+                char buf[65];
+                int i;
+
+                buf[0] = '\0';
+                for (i = 0; i < 32; i++) {
+                        if (ptr + i >= ((u_char *)calc_digest) + 16)
+                                break;
+                        sprintf(buf + i * 2, "%.2X", ptr[i]);
+                }
+                rc_log(LOG_ERR, "  %s", buf);
+        }
+	rc_log(LOG_ERR, "Reply digest is:");
+        for (ptr = (u_char *)reply_digest; ptr < ((u_char *)reply_digest) + 16; ptr += 32) {
+                char buf[65];
+                int i;
+
+                buf[0] = '\0';
+                for (i = 0; i < 32; i++) {
+                        if (ptr + i >= ((u_char *)reply_digest) + 16)
+                                break;
+                        sprintf(buf + i * 2, "%.2X", ptr[i]);
+                }
+                rc_log(LOG_ERR, "  %s", buf);
+        }
+#endif
+
+	if (memcmp ((char *) reply_digest, (char *) calc_digest,
+		    AUTH_VECTOR_LEN) != 0)
+	{
+		rc_log(LOG_ERR, "rc_check_reply: received invalid reply digest from RADIUS server");
+		return BADRESP_RC;
+	}
+
+	return OK_RC;
+
+}
+
+/** Generates a random vector of AUTH_VECTOR_LEN octets
+ *
+ * @param vector a buffer with at least %AUTH_VECTOR_LEN bytes.
+ */
+static void rc_random_vector (unsigned char *vector)
+{
+	int             randno;
+	int             i;
+#if defined(HAVE_GETENTROPY)
+	if (getentropy(vector, AUTH_VECTOR_LEN) >= 0) {
+		return;
+	} /* else fall through */
+#elif defined(HAVE_DEV_URANDOM)
+	int		fd;
+
+/* well, I added this to increase the security for user passwords.
+   we use /dev/urandom here, as /dev/random might block and we don't
+   need that much randomness. BTW, great idea, Ted!     -lf, 03/18/95	*/
+
+	if ((fd = open(_PATH_DEV_URANDOM, O_RDONLY)) >= 0)
+	{
+		unsigned char *pos;
+		int readcount;
+
+		i = AUTH_VECTOR_LEN;
+		pos = vector;
+		while (i > 0)
+		{
+			readcount = read(fd, (char *)pos, i);
+			if (readcount >= 0) {
+				pos += readcount;
+				i -= readcount;
+			} else {
+				if (errno != EINTR && errno != EAGAIN)
+					goto fallback;
+			}
+		}
+
+		close(fd);
+		return;
+	} /* else fall through */
+#endif
+ fallback:
+	for (i = 0; i < AUTH_VECTOR_LEN;)
+	{
+		randno = random ();
+		memcpy ((char *) vector, (char *) &randno, sizeof (int));
+		vector += sizeof (int);
+		i += sizeof (int);
+	}
+
+	return;
+}

+ 389 - 0
thirdparty/FreeRadius/lib/util.c

@@ -0,0 +1,389 @@
+/*
+ * $Id: util.c,v 1.10 2010/02/04 10:31:41 aland Exp $
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ *
+ * Copyright (C) 1995,1996,1997 Lars Fenneberg
+ *
+ * Copyright 1992 Livingston Enterprises, Inc.
+ *
+ * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
+ * and Merit Network, Inc. All Rights Reserved
+ *
+ * See the file COPYRIGHT for the respective terms and conditions.
+ * If the file is missing contact me at lf@elemental.net
+ * and I'll send you a copy.
+ *
+ */
+
+//#include <sys/time.h>
+
+#include <radius_config.h>
+#include <includes.h>
+#include <freeradius-client.h>
+#include "util.h"
+
+#define	RC_BUFSIZ	1024
+
+
+static char const * months[] =
+		{
+			"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+			"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+		};
+
+/** Turns printable string into correct tm struct entries
+ *
+ * @param valstr the printable date in 'day month year' format.
+ * @param tm the output struct.
+ */
+void rc_str2tm (char const *valstr, struct tm *tm)
+{
+	int             i;
+
+	/* Get the month */
+	for (i = 0; i < 12; i++)
+	{
+		if (strncmp (months[i], valstr, 3) == 0)
+		{
+			tm->tm_mon = i;
+			i = 13;
+		}
+	}
+
+	/* Get the Day */
+	tm->tm_mday = atoi (&valstr[4]);
+
+	/* Now the year */
+	tm->tm_year = atoi (&valstr[7]) - 1900;
+}
+
+/** Get the network interface name associated with this tty
+ *
+ * @param rh a handle to parsed configuration.
+ * @param tty the name of the tty.
+ * @return the network iface name.
+ */
+char *rc_getifname(rc_handle *rh, char const *tty)
+{
+#if defined(BSD4_4) || defined(linux)
+	int		fd;
+
+	if ((fd = open(tty, O_RDWR|O_NDELAY)) < 0) {
+		rc_log(LOG_ERR, "rc_getifname: can't open %s: %s", tty, strerror(errno));
+		return NULL;
+	}
+#endif
+
+#ifdef BSD4_4
+	strcpy(rh->ifname,ttyname(fd));
+	if (strlen(rh->ifname) < 1) {
+		rc_log(LOG_ERR, "rc_getifname: can't get attached interface of %s: %s", tty, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+#elif linux
+	if (ioctl(fd, SIOCGIFNAME, rh->ifname) < 0) {
+		rc_log(LOG_ERR, "rc_getifname: can't ioctl %s: %s", tty, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+#else
+	return NULL;
+#endif
+
+#if defined(BSD4_4) || defined(linux)
+	close(fd);
+	return rh->ifname;
+#endif
+}
+
+/** Reads in a string from the user (with or witout echo)
+ *
+ * @param rh a handle to parsed configuration.
+ * @param prompt the prompt to print.
+ * @param do_echo whether to echo characters.
+ * @return the data user typed or NULL.
+ */
+#ifndef _MSC_VER
+char *rc_getstr (rc_handle *rh, char const *prompt, int do_echo)
+{
+#if 0  
+	int             in, out;
+	char           *p;
+	struct termios  term_old, term_new;
+	int		is_term, flags, old_flags;
+	char		c;
+	int		flushed = 0;
+	sigset_t        newset;
+	sigset_t        oldset;
+
+	in = fileno(stdin);
+	out = fileno(stdout);
+
+	(void) sigemptyset (&newset);
+	(void) sigaddset (&newset, SIGINT);
+	(void) sigaddset (&newset, SIGTSTP);
+	(void) sigaddset (&newset, SIGQUIT);
+
+	(void) sigprocmask (SIG_BLOCK, &newset, &oldset);
+
+	if ((is_term = isatty(in)))
+	{
+
+		(void) tcgetattr (in, &term_old);
+		term_new = term_old;
+		if (do_echo)
+			term_new.c_lflag |= ECHO;
+		else
+			term_new.c_lflag &= ~ECHO;
+
+		if (tcsetattr (in, TCSAFLUSH, &term_new) == 0)
+			flushed = 1;
+
+	}
+	else
+	{
+		is_term = 0;
+		if ((flags = fcntl(in, F_GETFL, 0)) >= 0) {
+			old_flags = flags;
+			flags |= O_NONBLOCK;
+
+			fcntl(in, F_SETFL, flags);
+
+			while (read(in, &c, 1) > 0)
+				/* nothing */;
+
+			fcntl(in, F_SETFL, old_flags);
+
+			flushed = 1;
+		}
+	}
+
+	(void)write(out, prompt, strlen(prompt));
+
+	/* well, this looks ugly, but it handles the following end of line
+	   markers: \r \r\0 \r\n \n \n\r, at least at a second pass */
+
+	p = rh->buf;
+	for (;;)
+	{
+		if (read(in, &c, 1) <= 0)
+			return NULL;
+
+		if (!flushed && ((c == '\0') || (c == '\r') || (c == '\n'))) {
+			flushed = 1;
+			continue;
+		}
+
+		if ((c == '\r') || (c == '\n'))
+			break;
+
+		flushed = 1;
+
+		if (p < rh->buf + GETSTR_LENGTH)
+		{
+			if (do_echo && !is_term)
+				(void)write(out, &c, 1);
+			*p++ = c;
+		}
+	}
+
+	*p = '\0';
+
+	if (!do_echo || !is_term) (void)write(out, "\r\n", 2);
+
+	if (is_term)
+		tcsetattr (in, TCSAFLUSH, &term_old);
+	else {
+		if ((flags = fcntl(in, F_GETFL, 0)) >= 0) {
+			old_flags = flags;
+			flags |= O_NONBLOCK;
+
+			fcntl(in, F_SETFL, flags);
+
+			while (read(in, &c, 1) > 0)
+				/* nothing */;
+
+			fcntl(in, F_SETFL, old_flags);
+		}
+	}
+
+	(void) sigprocmask (SIG_SETMASK, &oldset, NULL);
+#endif
+	return rh->buf;
+}
+#endif
+
+void rc_mdelay(int msecs)
+{
+#if 0  
+	struct timeval tv;
+
+	tv.tv_sec = (int) msecs / 1000;
+	tv.tv_usec = (msecs % 1000) * 1000;
+
+	select(0, NULL, NULL, NULL, &tv);
+#endif    
+}
+
+/** Generate a quite unique string
+ *
+ * @note not that unique at all...
+ *
+ * @param rh a handle to parsed configuration.
+ * @return unique string. Memory does not need to be freed.
+ */
+
+char *rc_mksid (rc_handle *rh)
+{
+  //snprintf (rh->buf1, sizeof(rh->buf1), "%08lX%04X", (unsigned long int) time (NULL), (unsigned int) getpid ());
+  return rh->buf1;
+}
+
+/** Initialises new Radius Client handle
+ *
+ * @return a new rc_handle (free with rc_destroy).
+ */
+rc_handle *rc_new(void)
+{
+	rc_handle *rh;
+
+	rh = malloc(sizeof(*rh));
+	if (rh == NULL) {
+                rc_log(LOG_CRIT, "rc_new: out of memory");
+                return NULL;
+        }
+	memset(rh, 0, sizeof(*rh));
+	return rh;
+}
+
+/** Destroys Radius Client handle reclaiming all memory
+ *
+ * @param rh The Radius client handle to free.
+ */
+void rc_destroy(rc_handle *rh)
+{
+	rc_map2id_free(rh);
+	rc_dict_free(rh);
+	rc_config_free(rh);
+	free(rh);
+}
+
+/** Get next line from the stream.
+ *
+ * @param fp a %FILE pointer.
+ * @param len output length.
+ * @return the next line in an allocated buffer.
+ */
+char *rc_fgetln(FILE *fp, size_t *len)
+{
+	static char *buf = NULL;
+	static size_t bufsiz = 0;
+	char *ptr;
+
+	if (buf == NULL) {
+		bufsiz = RC_BUFSIZ;
+		if ((buf = malloc(bufsiz)) == NULL)
+			return NULL;
+	}
+
+	if (fgets(buf, (int)bufsiz, fp) == NULL)
+		return NULL;
+	*len = 0;
+
+	while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
+		size_t nbufsiz = bufsiz + RC_BUFSIZ;
+		char *nbuf = realloc(buf, nbufsiz);
+
+		if (nbuf == NULL) {
+			int oerrno = errno;
+			free(buf);
+			errno = oerrno;
+			buf = NULL;
+			return NULL;
+		} else
+			buf = nbuf;
+
+		*len = bufsiz;
+		if (fgets(&buf[bufsiz], RC_BUFSIZ, fp) == NULL)
+			return buf;
+
+		bufsiz = nbufsiz;
+	}
+
+	*len = (ptr - buf) + 1;
+	return buf;
+}
+
+/** Returns the current time as a double.
+ *
+ * @return current time (seconds since epoch) expressed as
+ * 	double-precision floating point number.
+ */
+double rc_getctime(void)
+{
+#if 0  
+    struct timeval timev;
+
+    if (gettimeofday(&timev, NULL) == -1)
+        return -1;
+
+    return timev.tv_sec + ((double)timev.tv_usec) / 1000000.0;
+#endif    
+    return RTC_GetUnixTime();
+}
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#ifndef HAVE_STRLCPY
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+rc_strlcpy(char *dst, char const *src, size_t siz)
+{
+    char *d = dst;
+    char const *s = src;
+    size_t n = siz;
+
+    /* Copy as many bytes as will fit */
+    if (n != 0 && --n != 0) {
+        do {
+            if ((*d++ = *s++) == 0)
+                break;
+        } while (--n != 0);
+    }
+
+    /* Not enough room in dst, add NUL and traverse rest of src */
+    if (n == 0) {
+        if (siz != 0)
+            *d = '\0';      /* NUL-terminate dst */
+        while (*s++)
+            ;
+    }
+
+    return(s - src - 1);    /* count does not include NUL */
+}
+
+#endif
+

+ 50 - 0
thirdparty/FreeRadius/lib/util.h

@@ -0,0 +1,50 @@
+/*
+ * util.h        Utility structures and prototypes.
+ *
+ * License:	BSD
+ *
+ */
+
+#ifndef UTIL_H
+# define UTIL_H
+
+#include <string.h>
+
+#ifndef HAVE_STRLCPY
+size_t rc_strlcpy(char *dst, char const *src, size_t siz);
+# define strlcpy rc_strlcpy
+#endif
+
+#include <includes.h>
+
+#if !defined(SA_LEN)
+#define SA_LEN(sa) \
+  (((sa)->sa_family == AF_INET) ? \
+    sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
+
+#define SS_LEN(sa) \
+  (((sa)->ss_family == AF_INET) ? \
+    sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
+#endif
+
+#define SA_GET_INADDR(sa) \
+  (((sa)->sa_family == AF_INET) ? \
+    ((void*)&(((struct sockaddr_in*)(sa))->sin_addr)) : ((void*)&(((struct sockaddr_in6*)(sa))->sin6_addr)))
+
+#define SA_GET_INLEN(sa) \
+  ((sa)->sa_family == AF_INET) ? \
+    sizeof(struct in_addr) : sizeof(struct in6_addr)
+
+//int rc_find_server_addr(rc_handle const *, char const *, struct addrinfo **, char *, unsigned flags);
+int rc_find_server_addr(rc_handle const *rh, char const *server_name, struct addrinfo** info, char *secret, unsigned flags);
+
+/* flags to rc_getaddrinfo() */
+#define PW_AI_PASSIVE		1
+#define PW_AI_AUTH		(1<<1)
+#define PW_AI_ACCT		(1<<2)
+
+struct addrinfo *rc_getaddrinfo (char const *host, unsigned flags);
+void rc_own_bind_addr(rc_handle *rh, struct sockaddr_storage *lia);
+
+#endif /* UTIL_H */
+

+ 103 - 0
thirdparty/FreeRadius/radius_config.h

@@ -0,0 +1,103 @@
+/******************************* (C) LiteMesh **********************************
+ * @module  template
+ * @file    template.h
+ * @version 1.0.0
+ * @date    XX.XX.XXXX
+ * $brief   template
+ *******************************************************************************
+ * @history     Version  Author         Comment
+ * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
+ *******************************************************************************
+ */
+
+/* Define to prevent recursive  ----------------------------------------------*/
+#ifndef __RADIUS_CONFIG_H
+#define __RADIUS_CONFIG_H
+
+#include <stdint.h>
+#include <string.h>
+
+#define RC_LOG
+#define STDC_HEADERS
+#define HAVE_RAND       //  Рандом генератор
+//#define HAVE_GETENTROPY // ?
+
+// some unix defines
+#define LOG_CRIT    0
+#define LOG_ERR     0
+#define LOG_WARNING 0
+
+//typedef unsigned int size_t;
+
+// some unix structs
+
+/*
+ * Desired design of maximum size and alignment (see RFC2553)
+ */
+#define _K_SS_MAXSIZE	128	/* Implementation specific max size */
+#define _K_SS_ALIGNSIZE	(__alignof__ (struct sockaddr *))
+				/* Implementation specific desired alignment */
+
+typedef unsigned short __kernel_sa_family_t;
+
+struct __kernel_sockaddr_storage {
+	__kernel_sa_family_t	ss_family;		/* address family */
+	/* Following field(s) are implementation specific */
+	char		data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+				/* space to achieve desired size, */
+				/* _SS_MAXSIZE value minus size of ss_family */
+} ;	/* force desired alignment */
+
+// -----------------------------------------------------------------------------
+
+typedef __kernel_sa_family_t	sa_family_t;
+
+// -----------------------------------------------------------------------------
+/*
+struct sockaddr {
+	char	sa_len;			// total length 
+	char	sa_family;		// address family 
+	char	sa_data[14];	// actually longer; address value 
+};
+*/
+
+#define _SS_MAXSIZE    128  /* Implementation specific max size */
+#define _SS_ALIGNSIZE  (sizeof (int64_t))
+
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof(sa_family_t)+ \
+                      _SS_PAD1SIZE + _SS_ALIGNSIZE))
+struct sockaddr_storage {
+    sa_family_t  ss_family;  /* Address family. */
+/*
+ *  Following fields are implementation-defined.
+ */
+    char _ss_pad1[_SS_PAD1SIZE];
+        /* 6-byte pad; this is to make implementation-defined
+           pad up to alignment field that follows explicit in
+           the data structure. */
+    int64_t _ss_align;  /* Field to force desired structure
+                           storage alignment. */
+    char _ss_pad2[_SS_PAD2SIZE];
+        /* 112-byte pad to achieve desired size,
+           _SS_MAXSIZE value minus size of ss_family
+           __ss_pad1, __ss_align fields is 112. */
+};
+
+
+struct addrinfo {
+    int              ai_flags;     // AI_PASSIVE, AI_CANONNAME, etc.
+    int              ai_family;    // AF_INET, AF_INET6, AF_UNSPEC
+    int              ai_socktype;  // SOCK_STREAM, SOCK_DGRAM
+    int              ai_protocol;  // use 0 for "any"
+    size_t           ai_addrlen;   // size of ai_addr in bytes
+    struct sockaddr *ai_addr;      // struct sockaddr_in or _in6
+    char            *ai_canonname; // full canonical hostname
+
+    struct addrinfo *ai_next;      // linked list, next node
+};
+
+
+#endif /* #ifndef __RADIUS_CONFIG_H */
+
+/****************************** (C) LiteMesh ***************** end of file ****/

+ 20 - 10
user/init_task.c

@@ -35,6 +35,7 @@
 //#include "ups_params.h"
 //#include "ups_monitor.h"
 //#include <lwip/stats.h>
+#include "radius_user.h"
 
 #ifdef PRINTF_STDLIB
 #include <stdio.h>
@@ -77,6 +78,8 @@ void InitTask(void *params)
 // -----------------------------------------------------------------------------    
   InitUSART();
   ups_megatec_init();
+
+  log_init(false);
 // -----------------------------------------------------------------------------    
  // RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
   //SETTINGS_SetDefaultDebug();
@@ -136,11 +139,22 @@ void InitTask(void *params)
   LwIP_Init();
   
 #ifdef WEB_SERVER_ENABLE
-  //HTTP_Init();
-  HTTPS_Init();
+  if(strncmp(sSettings.sFlags.testState, "T2OK", 4)){
+
+	  HTTP_Init();
+  	  xTaskCreate(vTaskTesting, "Testing", configMINIMAL_STACK_SIZE,
+                NULL, tskIDLE_PRIORITY, NULL);
+    }
+  else{
+	   HTTPS_Init();
 #define SSL_TASK_PRIO   ( configMAX_PRIORITIES - 3 )
-  xTaskCreate(ssl_server, "SSL", 10*configMINIMAL_STACK_SIZE, NULL, SSL_TASK_PRIO, NULL); 
+	   xTaskCreate(ssl_server, "SSL", 10*configMINIMAL_STACK_SIZE, NULL, SSL_TASK_PRIO, NULL);
 #endif
+	   /* UDP for net settings */
+	  	  UDP_netsetting_init();
+  }
+
+
   
 #ifdef SNMP_ENABLE
 
@@ -164,8 +178,7 @@ void InitTask(void *params)
 				 NULL, tskIDLE_PRIORITY, NULL);
 // -----------------------------------------------------------------------------  
 
-	 /* UDP for net settings */
-	  UDP_netsetting_init();
+
 // Тестирование
     
   // Тест таблицы трапов  
@@ -178,11 +191,6 @@ void InitTask(void *params)
 #endif  
 // -----------------------------------------------------------------------------      
 
- /* if(strncmp(sSettings.sFlags.testState, "T2OK", 4)){
-	  xTaskCreate(vTaskTesting, "Testing", configMINIMAL_STACK_SIZE,
-              NULL, tskIDLE_PRIORITY, NULL);
-  }*/
-
   //TEST_InitRS485();
   //TEST_IO();
   
@@ -193,6 +201,8 @@ void InitTask(void *params)
   vTaskDelay(4000);
  
   SETTINGS_ResetBootTry();
+
+ // RC_Login("test1", "12345");
   
   // Отправка трапа о перезагрузке в случае статического IP
  /* if (!dhcp)

+ 4 - 1
user/main.c

@@ -3,6 +3,7 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "common_config.h"
+#include "settings_api.h"
 
 #include "gpio.h"
 
@@ -50,10 +51,12 @@ int main()
 	WDG_Init();
 
 	spi_flash_init();
-	log_init(false);
+	//log_init(false);
 	//log_test();
 	//spi_flash_test();
 //  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
+
+	init_settings();
   
   xTaskCreate( InitTask, "InitTask", 1000, NULL, tskIDLE_PRIORITY, NULL);
   

+ 4 - 4
user/main.h

@@ -58,13 +58,13 @@
 #define __packed		__attribute__(( packed ))
 #endif
    
-//#define DEBUG
+//#define OUR_DEBUG
 
-/*#ifdef DEBUG
+#ifdef OUR_DEBUG
 #define DBG
-#else*/
+#else
 #define DBG if (0)
-//#endif
+#endif
 
    
 /* Exported macro ------------------------------------------------------------*/

+ 1 - 0
web_interface/Gruntfile.js

@@ -62,6 +62,7 @@ module.exports = function (grunt) {
         },
         files: {
           'src/wui/login.min.html':       'src/wui/login.html',
+          'src/wui/rslogin.min.html':     'src/wui/rslogin.html',
           'src/wui/index.min.html':       'src/wui/index.html',
           'src/wui/settings.min.html':    'src/wui/settings.html',
           'src/wui/info.min.html':        'src/wui/info.html',

BIN
web_interface/error.html


BIN
web_interface/index.html


BIN
web_interface/login.html


+ 1 - 1
web_interface/src/wui/info.html

@@ -29,7 +29,7 @@
 <table class="table wrapper-default tb-info">
   <thead>
     <tr>
-      <th colspan="2">Контроллер</th>
+      <th colspan="2">Контроллер мониторинга</th>
     </tr>
   </thead>
   <tbody>

+ 2 - 2
web_interface/src/wui/login.html

@@ -20,7 +20,7 @@
 
   <div class="panel panel-default">
     <div class="panel-body">
-      <form action="login.cgi" method="post" class="login-form">
+      <form action="login.cgi" method="post" class="login-form form-inline">
         <label for="login">Логин:&nbsp;</label>
         <input type="text" class="form-control" name="login" id="login" maxlength="16" style="margin-right: 10px;">
         <label for="pass">Пароль:&nbsp;</label>
@@ -32,4 +32,4 @@
 <!--END-->
 </div>
 </body>
-</html>
+</html>

+ 487 - 232
web_interface/src/wui/main.css

@@ -1,9 +1,429 @@
-/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
-img,legend{border:0}legend,td,th{padding:0}html{font-family:Arial, Helvetica, sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre,textarea{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit;}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}table{border-spacing:0;border-collapse: separate;}
+html {
+  font-family: sans-serif; /* 1 */
+  -ms-text-size-adjust: 100%; /* 2 */
+  -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove the margin in all browsers (opinionated).
+ */
+
+body {
+  margin: 0;
+}
+
+/* HTML5 display definitions
+   ========================================================================== */
+
+/**
+ * Add the correct display in IE 9-.
+ * 1. Add the correct display in Edge, IE, and Firefox.
+ * 2. Add the correct display in IE.
+ */
+
+article,
+aside,
+details, /* 1 */
+figcaption,
+figure,
+footer,
+header,
+main, /* 2 */
+menu,
+nav,
+section,
+summary { /* 1 */
+  display: block;
+}
+
+/**
+ * Add the correct display in IE 9-.
+ */
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+/**
+ * Add the correct display in iOS 4-7.
+ */
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+  vertical-align: baseline;
+}
+
+/**
+ * Add the correct display in IE 10-.
+ * 1. Add the correct display in IE.
+ */
+
+template, /* 1 */
+[hidden] {
+  display: none;
+}
+
+/* Links
+   ========================================================================== */
+
+/**
+ * 1. Remove the gray background on active links in IE 10.
+ * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
+ */
+
+a {
+  background-color: transparent; /* 1 */
+  -webkit-text-decoration-skip: objects; /* 2 */
+}
+
+/**
+ * Remove the outline on focused links when they are also active or hovered
+ * in all browsers (opinionated).
+ */
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+/* Text-level semantics
+   ========================================================================== */
+
+/**
+ * 1. Remove the bottom border in Firefox 39-.
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+  border-bottom: none; /* 1 */
+  text-decoration: underline; /* 2 */
+  text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
+ */
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+/**
+ * Add the correct font style in Android 4.3-.
+ */
+
+dfn {
+  font-style: italic;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+/**
+ * Add the correct background and color in IE 9-.
+ */
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+  font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+/* Embedded content
+   ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10-.
+ */
+
+img {
+  border-style: none;
+}
+
+/**
+ * Hide the overflow in IE.
+ */
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+/* Grouping content
+   ========================================================================== */
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace; /* 1 */
+  font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct margin in IE 8.
+ */
+
+figure {
+  margin: 1em 40px;
+}
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+  box-sizing: content-box; /* 1 */
+  height: 0; /* 1 */
+  overflow: visible; /* 2 */
+}
+
+/* Forms
+   ========================================================================== */
+
+/**
+ * 1. Change font properties to `inherit` in all browsers (opinionated).
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit; /* 1 */
+  margin: 0; /* 2 */
+}
+
+/**
+ * Restore the font weight unset by the previous rule.
+ */
+
+optgroup {
+  font-weight: bold;
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+  overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+  text-transform: none;
+}
+
+/**
+ * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
+ *    controls in Android 4.
+ * 2. Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+html [type="button"], /* 1 */
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button; /* 2 */
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+/**
+ * Change the border, margin, and padding in all browsers (opinionated).
+ */
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ *    `fieldset` elements in all browsers.
+ */
+
+legend {
+  box-sizing: border-box; /* 1 */
+  color: inherit; /* 2 */
+  display: table; /* 1 */
+  max-width: 100%; /* 1 */
+  padding: 0; /* 3 */
+  white-space: normal; /* 1 */
+}
+
+/**
+ * Remove the default vertical scrollbar in IE.
+ */
+
+textarea {
+  overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10-.
+ * 2. Remove the padding in IE 10-.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+  box-sizing: border-box; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+input[type="search"] {
+  -webkit-appearance: textfield; /* 1 */
+  outline-offset: -2px; /* 2 */
+}
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
 
+::-webkit-file-upload-button {
+  -webkit-appearance: button; /* 1 */
+  font: inherit; /* 2 */
+}
 
 /* Main style */
-body {background-color: #E8EBF1; color: #333;overflow-y: scroll; height: 100%;}
+* {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+html {
+  font-family:Arial, Helvetica, sans-serif;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+input,
+button,
+select,
+textarea {
+  font-family: inherit;
+  font-size: inherit;
+  line-height: inherit;
+}
+body {background-color: #E8EBF1; color: #333;overflow-y: scroll; height: 100%; line-height: 1.42857143;}
 
 .clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical > .btn-group:before,.btn-group-vertical > .btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after
 {display: table;content: " ";}
@@ -1262,6 +1682,8 @@ label {
   font-size: .9em;
   padding-top: 3px;
   color: #666;
+  max-width: 100%;
+  margin-bottom: 5px;
 }
 .checkbox{
   display: block;
@@ -1395,86 +1817,7 @@ label {
   line-height: 1.5;
   border-radius: 0;
 }
-.spinBox{
-  width: 100%;
-  position      : relative;
-  display       : inline-block;
-  padding-bottom: 5px;
-  -webkit-appearance: none;
-}
-
-.spinBox input{
-  width: 100%;
-  display       : block;
-  // border        : 0.0625em solid rgb(224,224,224);
-  border-right  : none;
-  text-align    : center;
-  -webkit-appearance: none;
-  padding: 8px 7px;
-  font-size: 14px;
-  color: #555;
-  background-color: #fff;
-  background-image: none;
-  border: 1px solid #ccc;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-          box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-}
-.spinBox input:focus {
-  border-color: #66afe9;
-  outline: 0;
-  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
-          box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
-}
-.spinBox input[disabled]{
-  background : rgb(240,240,240);
-}
-
-.spinBoxUp,
-.spinBoxDown{
-  position         : absolute;
-  display          : block;
-  width            : 2em;
-  height           : 2em;
-  border           : 0.0625em solid rgb(224,224,224);
-  background       : rgb(248,248,248);
-  cursor           : pointer;
-  font-weight: bold;
-}
-
-.spinBox input[disabled] + span,
-.spinBox input[disabled] + span + span{
-  background : rgb(240,240,240);
-  cursor     : auto;
-}
-
-.spinBoxUp span,
-.spinBoxDown span{
-  display : block;
-  width   : 1em;
-  height  : 1em;
-}
 
-.spinBoxUp{
-  text-align: center;
-  line-height: 2em;
-  vertical-align:middle;
-  right: 0;
-  top: 0;
-}
-.spinBoxDown{
-  vertical-align:middle;
-  line-height: 2em;
-  text-align: center;
-  top: 0;
-  left: 0;
-}
-.spinboxMark{
-  position: absolute;
-  text-align: center;
-  font-style: italic;
-  padding: 0.3em;
-  height  : 1.59em;
-}
 a.btn {text-decoration: none;}
 [role="button"] {cursor: pointer;}
 
@@ -1569,12 +1912,16 @@ ul#validation-box{
   color: #fff;
 }
 
-
+.form-group {
+  display: inline-block;
+  vertical-align: middle;
+  margin: -3px -5px 10px 0 !important;
+}
 
 .form-control {
-  display: inline-block;
+  display: block;
   width: 100%;
-  /*height: 26px;*/
+  height: 34px;
   padding: 6px 12px;
   font-size: 14px;
   line-height: 1.42857143;
@@ -1585,6 +1932,9 @@ ul#validation-box{
   border-radius: 0;
   -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
           box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+       -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+          transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
 }
 .form-control:focus {
   border-color: #66afe9;
@@ -1600,17 +1950,57 @@ ul#validation-box{
 .form-control[disabled],fieldset[disabled] .form-control {cursor: not-allowed;}
 textarea.form-control {height: auto;}
 input[type="search"] {-webkit-appearance: none;}
-// @media screen and (-webkit-min-device-pixel-ratio: 0) {
-//   input[type="date"].form-control,
-//   input[type="time"].form-control,
-//   input[type="datetime-local"].form-control,
-//   input[type="month"].form-control {
-//     line-height: 34px;
-//   }
-// }
-/*.form-group {
-  margin-bottom: 15px;
-}*/
+
+@media (min-width: 768px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio,
+  .form-inline .checkbox {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .radio label,
+  .form-inline .checkbox label {
+    padding-left: 0;
+  }
+  .form-inline .radio input[type="radio"],
+  .form-inline .checkbox input[type="checkbox"] {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
 .radio,
 .checkbox {
   position: relative;
@@ -1653,6 +2043,7 @@ input[type="search"] {-webkit-appearance: none;}
   margin-top: 0;
   margin-left: 10px;
 }
+input { line-height: normal; }
 input[type="radio"][disabled],
 input[type="checkbox"][disabled],
 input[type="radio"].disabled,
@@ -1923,141 +2314,6 @@ span .editable-click:hover {
   border-bottom: dashed 1px #08C;
 }
 
-.tip-box {
-    position: absolute;
-    z-index: 1060;
-    max-width: 276px;
-    padding:10px;
-    background: #fff;
-    box-shadow: 0 1px 5px rgba(0,0,0,0.15);
-    -webkit-background-clip: padding-box;
-    background-clip: padding-box;
-    border: 1px solid #ccc;
-}
-
-.tip-box.top {
-    margin-top: -10px;
-}
-
-.tip-box.right {
-    margin-left: 10px
-}
-
-.tip-box.bottom {
-    margin-top: 10px
-}
-
-.tip-box.left {
-    margin-left: -10px
-}
-
-.tip-box-title {
-    padding: 8px 14px;
-    margin: 0;
-    font-size: 14px;
-    background-color: #f7f7f7;
-    border-bottom: 1px solid #ebebeb;
-    border-radius: 0;
-}
-
-.tip-box-content {
-    padding: 9px 14px
-}
-
-.tip-box>.arrow,.tip-box>.arrow:after {
-    position: absolute;
-    display: block;
-    width: 0;
-    height: 0;
-    border-color: transparent;
-    border-style: solid
-}
-
-.tip-box>.arrow {
-    border-width: 11px
-}
-
-.tip-box>.arrow:after {
-    content: "";
-    border-width: 10px
-}
-
-.tip-box.top>.arrow {
-    bottom: -11px;
-    left: 20%;
-    margin-left: -11px;
-    border-top-color: #999;
-    border-top-color: rgba(0,0,0,.25);
-    border-bottom-width: 0
-}
-
-.tip-box.top>.arrow:after {
-    bottom: 1px;
-    margin-left: -10px;
-    content: " ";
-    border-top-color: #fff;
-    border-bottom-width: 0
-}
-
-.tip-box.right>.arrow {
-    top: 50%;
-    left: -11px;
-    margin-top: -11px;
-    border-right-color: #999;
-    border-right-color: rgba(0,0,0,.25);
-    border-left-width: 0
-}
-
-.tip-box.right>.arrow:after {
-    bottom: -10px;
-    left: 1px;
-    content: " ";
-    border-right-color: #fff;
-    border-left-width: 0
-}
-
-.tip-box.bottom>.arrow {
-    top: -11px;
-    left: 50%;
-    margin-left: -11px;
-    border-top-width: 0;
-    border-bottom-color: #999;
-    border-bottom-color: rgba(0,0,0,.25)
-}
-
-.tip-box.bottom>.arrow:after {
-    top: 1px;
-    margin-left: -10px;
-    content: " ";
-    border-top-width: 0;
-    border-bottom-color: #fff
-}
-
-.tip-box.left>.arrow {
-    top: 50%;
-    right: -11px;
-    margin-top: -11px;
-    border-right-width: 0;
-    border-left-color: #999;
-    border-left-color: rgba(0,0,0,.25)
-}
-
-.tip-box.left>.arrow:after {
-    right: 1px;
-    bottom: -10px;
-    content: " ";
-    border-right-width: 0;
-    border-left-color: #fff
-}
-
-.tip-box > input.form-control {
-  height: 37px;
-}
-.tip-box > select.form-control {
-  height: 37px;
-}
-
-
 #show_hide{
   display: inline-block;
   color: #747589;
@@ -2336,7 +2592,6 @@ input.login {
   display: block;
   float:left;
   margin: 1% 0 1% 1%;
-  padding-top: 1px;
 }
 
 /*.col:first-child { margin-left: 0; }*/ /* all browsers except IE6 and lower */

+ 1 - 1
web_interface/src/wui/main.js

@@ -377,7 +377,7 @@ function getCGI(url) {
   var xmlhttp;
   var q;
   if (url == 'reset.cgi') {
-    q = confirm('Вы уверены что хотите сбросить на заводские настройки?');
+    q = confirm('Вы уверены что хотите сбросить в заводские настройки?');
   }
   if (url == 'reboot.cgi') {
     q = confirm('Вы уверены что хотите перезагрузить устройство?');

+ 35 - 0
web_interface/src/wui/rslogin.html

@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="">
+<head>
+<meta charset="utf-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
+<title>Мониторинг</title>
+<link href="main.css" rel="stylesheet">
+<script type="text/javascript" src="role.js"></script>
+</head>
+<body>
+  <div class="navbar navbar-default navbar-fixed-top">
+    <div class="navbar-header">
+      <div><a href="#" class="logo"></a></div>
+    </div>
+  </div>
+  <div class="wrapper" id="content">
+<!--START-->
+<h1>Radius Авторизация</h1>
+
+  <div class="panel panel-default">
+    <div class="panel-body">
+      <form action="login.cgi" method="post" class="login-form form-inline">
+        <label for="login">Логин:&nbsp;</label>
+        <input type="text" class="form-control" name="login" id="login" maxlength="16" style="margin-right: 10px;">
+        <label for="pass">Пароль:&nbsp;</label>
+        <input type="password" class="form-control" name="password" id="pass" maxlength="16">
+        <input type="submit" class="btn btn-primary" value="Войти">
+      </form>
+    </div>
+  </div>
+<!--END-->
+</div>
+</body>
+</html>

+ 21 - 17
web_interface/src/wui/settings.html

@@ -21,9 +21,9 @@
         <option value="user">user</option>
         <option value="admin">admin</option>
       </select><br><br>
-      <input id="oldpwd" type="password" class="form-control" placeholder="Текущий пароль" class="login" size="20" maxlength="16" name="oldpass"><br><br>
-      <input id="newpwd" type="password" class="form-control" placeholder="Новый пароль" class="login" size="20" maxlength="16" name="newpass"><br><br>
-      <input id="newpwdrepeat" type="password" class="form-control" placeholder="Повторить новый пароль" class="login" size="20" maxlength="16" name="newpassRepeat"><br><br>
+      <input id="oldpwd" type="password" class="form-control" placeholder="Текущий пароль" class="login" size="20" maxlength="16" name="oldpass" autocomplete="off"><br><br>
+      <input id="newpwd" type="password" class="form-control" placeholder="Новый пароль" class="login" size="20" maxlength="16" name="newpass" autocomplete="off"><br><br>
+      <input id="newpwdrepeat" type="password" class="form-control" placeholder="Повторить новый пароль" class="login" size="20" maxlength="16" name="newpassRepeat" autocomplete="off"><br><br>
       <input type="button" id="close-pass-change" class="btn btn-danger-inverted" value="Отмена">
       <input type="submit" class="btn btn-success-inverted" onclick="checkChangePWD(); return false;" value="Отправить">
     </form>
@@ -183,16 +183,18 @@
   <div class="panel-body section group">
     <div class="col span_1_of_3">
       <h4 class="col span_2_of_2">Аккумуляторные батареи</h4>
-      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'stop' });">Остановка теста</button>
-      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'discharge' });">Запуск теста до разряда</button>
-      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'time', 'time': $('test_time').value });">Запуск теста</button>
-      <label for="" class="col span_1_of_2">Время теста (мин)</label>
-      <div class="col span_1_of_2">
-        <input type="text" class="form-control" value="10" maxlength="6" id="test_time">
+      <div class="form-group">
+        <label for="" class="col span_1_of_2">Время теста (мин)</label>
+        <div class="col span_1_of_2">
+          <input type="text" class="form-control" value="10" maxlength="6" id="test_time">
+        </div>
       </div>
+      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'time', 'time': $('test_time').value });">Запуск теста</button>
+      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'discharge' });">Запуск теста до разряда</button>
+      <button type="button" class="btn btn-default" onclick="batTest({ 'func': 'stop' });">Остановка теста</button>
     </div>
     <div class="col span_1_of_3">
-      <h4 class="col span_2_of_2">Контроллер</h4>
+      <h4 class="col span_2_of_2">Контроллер мониторинга</h4>
       <button type="button" class="btn btn-default" id="change_pass">Смена пароля</button>
       <button type="button" class="btn btn-default" id="dev-reboot">Перезагрузка</button>
       <button type="button" class="btn btn-default" id="dev-update">Обновление ПО</button>
@@ -201,9 +203,11 @@
       <h4 class="col span_2_of_2">Нагрузка</h4>
       <button type="button" class="btn btn-default" onclick="UPSPowerOff({'func': 'reboot'})">Отмена отключения</button>
       <button type="button" class="btn btn-default" onclick="UPSPowerOff({'func': 'off', 'after': $('upspo_after').value})">Отключить</button>
-      <label for="" class="col span_1_of_2">Откл. через (мин)</label>
-      <div class="col span_1_of_2">
-        <input type="text" class="form-control" value="10" maxlength="6" id="upspo_after">
+      <div class="form-group">
+        <label for="" class="col span_1_of_2">Откл. через (мин)</label>
+        <div class="col span_1_of_2">
+          <input type="text" class="form-control" value="10" maxlength="6" id="upspo_after">
+        </div>
       </div>
     </div>
   </div>
@@ -228,11 +232,11 @@
       </div>
       <label for="rs_pwd" class="col span_1_of_2">Пароль</label>
       <div class="col span_1_of_2">
-        <input type="password" class="form-control" id="rs_pwd" name="rs_pwd">
+        <input type="text" class="form-control" id="rs_pwd" name="rs_pwd">
       </div>
-      <label for="rs_key" class="col span_1_of_2">Код access</label>
-      <div class="col span_1_of_2">
-        <input type="password" class="form-control" id="rs_key" name="rs_key">
+      <label for="rs_key" class="col span_1_of_2 hidden">Код access</label>
+      <div class="col span_1_of_2 hidden">
+        <input type="text" class="form-control" id="rs_key" name="rs_key">
       </div>
     </div>
     <div class="col span_1_of_2">

+ 1 - 1
web_interface/src/wui/ups_history.html

@@ -34,7 +34,7 @@
   <thead>
     <tr>
       <th class="ph2">Вх. напр.</th>
-      <th class="ph2">Напр. на вх.</th>
+      <th class="ph2">Ав. вх. напр.</th>
       <th class="ph2">Вых. напр.</th>
       <th class="ph2">Нагрузка</th>
       <th class="ph2">Вх. частота</th>

BIN
web_interface/success.html


BIN
web_interface/upload.css


BIN
web_interface/upload.js


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio