--- busybox-1.11.2-orig/sysklogd/klogd.c	2008-06-25 20:51:17.000000000 +0800
+++ busybox-1.11.2/sysklogd/klogd.c 	2011-02-15 13:35:14.077250000 +0800
@@ -102,6 +102,7 @@
 				//	priority = priority * 10 + (log_buffer[i] - '0');
 				//	i++;
 				//}
+#if 0 //fanny---- Kernel priority may have chance to be one digit larger than 7 because of draytek syslog level				
 				if (isdigit(log_buffer[i])) {
 					priority = (log_buffer[i] - '0');
 					i++;
@@ -109,6 +110,41 @@
 				if (log_buffer[i] == '>')
 					i++;
 				start = &log_buffer[i];
+#else
+				priority = (log_buffer[i] - '0');
+				i++;
+				if (log_buffer[i] == '>')
+					i++;
+				start = &log_buffer[i];
+
+				if(priority > 7){ // kernel draytek log priority
+					/* Modify kernel mode priority to user mode priority value */
+					switch(priority){
+						case 8: // ROUTER_STATUS_INFO
+							priority = ROUTER_STATUS_INFO;
+							break;
+						case 9: // WANLOG_INFO
+							priority = WANLOG_INFO;
+							break;
+						case 10: // IPFLOG_INFO
+							priority = IPFLOG_INFO;
+							break;
+						case 11: // IPFLOG_ALERT
+							priority = IPFLOG_ALERT;
+							break;
+						case 12: // CALLLOG_INFO
+							priority = CALLLOG_INFO;
+							break;
+						case 13: // USRLOG_INFO
+							priority = USRLOG_INFO;
+							break;
+						case 14: // VPNLOG_INFO
+							priority = VPNLOG_INFO;
+							break;
+					}
+				}				
+#endif
+
 			}
 			while (log_buffer[i] != '\n')
 				i++;
--- busybox-1.11.2-orig/sysklogd/syslogd.c	2008-06-25 20:51:17.000000000 +0800
+++ busybox-1.11.2/sysklogd/syslogd.c 	2011-02-15 13:36:20.327250000 +0800
@@ -36,7 +36,21 @@
 #endif
 
 
-#define DEBUG 0
+#define	ENABLE_SYSLOG_CLASS		1
+#define	DEBUG					0
+
+#if ENABLE_SYSLOG_CLASS
+	#if ENABLE_FEATURE_SYSLOGD_DUP
+		#error...we should not enable both syslog class and syslog dup
+	#endif
+	#define	MAX_HEAD_ROOM		16
+	unsigned char	*tx_syslog_buf = NULL;
+#endif
+
+/* Draytek modification */
+#define		DRAY_SYSLOG_BUF_SIZE		4096
+unsigned char	syslog_buf[DRAY_SYSLOG_BUF_SIZE];
+/**************************************************/
 
 /* MARK code is not very useful, is bloat, and broken:
  * can deadlock if alarmed to make MARK while writing to IPC buffer
@@ -104,7 +118,11 @@
 	char *hostname;
 
 	/* We recv into recvbuf... */
+#if ENABLE_SYSLOG_CLASS	
+	char recvbuf[MAX_READ + MAX_HEAD_ROOM];
+#else
 	char recvbuf[MAX_READ * (1 + ENABLE_FEATURE_SYSLOGD_DUP)];
+#endif
 	/* ...then copy to parsebuf, escaping control chars */
 	/* (can grow x2 max) */
 	char parsebuf[MAX_READ*2];
@@ -471,11 +489,185 @@
 		*q = '\0';
 
 		/* Now log it */
-		if (LOG_PRI(pri) < G.logLevel)
+		if (LOG_PRI(pri) < G.logLevel && pri != USRLOG_INFO ) // skip USER ACCESS Log in local 
 			timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
 	}
 }
 
+/*******************Draytek ************************/
+
+void busybox_direct_printf(const char *format, ...) 
+{
+	char  wimax_print_buf[200]; 
+	int                 len;
+	va_list             args;
+	int	fd;
+
+	// Build MSG
+	va_start(args, format);
+	len = vsprintf(wimax_print_buf, format, args);
+	va_end(args);
+
+	fd = open("/dev/console", O_WRONLY);
+	if(!fd){
+		return;
+	}
+	write(fd, wimax_print_buf, len);
+	//printf("%s\r\n", wimax_print_buf);
+	close(fd);
+}
+
+
+void dbg_mem_dump(unsigned char *ptr, int len)
+{
+	int i;
+
+	busybox_direct_printf("dump memory : %x(len=%d)\r\n", ptr, len);
+
+	for(i=0; i<len; i++){
+		busybox_direct_printf("%02x ", *(ptr+i));
+		if((i+1) % 8 == 0){
+			busybox_direct_printf("\r\n");
+		}
+	}
+	busybox_direct_printf("\r\n");	
+}
+
+
+#if ENABLE_SYSLOG_CLASS // fanny -- syslog classification
+
+int check_is_draytek_syslog(int pri)
+{
+	int ret;
+
+	switch(pri){
+		case ROUTER_STATUS_INFO:
+		case WANLOG_INFO:
+		case IPFLOG_INFO:
+		case IPFLOG_ALERT:
+		case CALLLOG_INFO:
+		case USRLOG_INFO:
+		case VPNLOG_INFO:
+			ret = 1;
+			break;
+		default:
+			ret = 0;
+	}
+	return ret;
+}
+
+
+int parse_log_level(char *tmpbuf, int len)
+{
+	char *p = tmpbuf;
+	char *end = tmpbuf + len;
+	smallint	ori_logmode;
+	char	buf[512];
+	char *ptr1, *ptr2, *ori_ptr;
+	int classify;
+
+	//busybox_direct_printf("Original syslog buffer......\r\n");
+	//dbg_mem_dump(tmpbuf, len);
+	ori_ptr = tmpbuf;
+
+	while (p < end) {
+		char c;
+		char *q = G.parsebuf;
+		int pri = (LOG_USER | LOG_NOTICE);
+
+		if (*p == '<') {
+			int size, result;
+
+			ptr1 = p; // pointer address of '<'
+
+			/* Parse the magic priority number */
+			pri = bb_strtou(p + 1, &p, 10);
+			if (*p == '>')
+				p++;
+
+			ptr2 = p; // pointer address after '>'
+
+			//busybox_direct_printf("---> prio = 0x%x\r\n", pri);
+
+			classify = check_is_draytek_syslog(pri);
+
+			if(classify){
+				// If enable syslog classification, try to change packet contents to another buffer.
+				// Don't reuse the facility element because the size is not fixed(2 or 3 bytes...etc..)
+				int first_size = (int)(ptr1 - tmpbuf);
+				unsigned char *new_ptr;
+				int size, new_size, i;
+				char buf[64];
+				
+				sprintf(buf, "<%d>", pri); // pass CALLLOG_INFO
+				new_size = strlen(buf);
+				size = (int)p - (int)tmpbuf; // try to calculate the bytes between <>.
+
+				//busybox_direct_printf("tmpbuf = 0x%x, ptr1 = 0x%x, ptr2 = 0x%x\r\n", tmpbuf, ptr1, ptr2);
+				if(new_size != size){
+					if(new_size - size == 1){ // new facility is larger than original (one byte).
+						//busybox_direct_printf("size = %d --> %d\r\n", size, new_size);
+
+						// shift data one byte ahead
+						for(i=0; i<first_size; i++){
+							*((char *)(ori_ptr-1+i)) = ori_ptr[i]; // move data one byte ahead
+						}
+
+						memcpy(ori_ptr-1, buf, new_size);
+						//busybox_direct_printf("New syslog buffer......\r\n");
+						//dbg_mem_dump(ori_ptr-1, len+1);
+						tx_syslog_buf = ori_ptr - 1;
+					}else{
+						printf("Fanny : syslog convert error %d --> %d\r\n", size, new_size);
+						tx_syslog_buf = ori_ptr;
+					}
+				}else{
+					memcpy(ptr1, buf, new_size);
+					tx_syslog_buf = ori_ptr;
+				}
+			}else{
+				tx_syslog_buf = ori_ptr;
+			}
+
+			if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
+				pri = (LOG_USER | LOG_NOTICE);
+
+			return pri;
+		}
+	}
+	return 0;
+}
+
+#else
+
+int parse_log_level(char *tmpbuf, int len)
+{
+	char *p = tmpbuf;
+	char *end = tmpbuf + len;
+
+	while (p < end) {
+		char c;
+		char *q = G.parsebuf;
+		int pri = (LOG_USER | LOG_NOTICE);
+
+		if (*p == '<') {
+			/* Parse the magic priority number */
+			pri = bb_strtou(p + 1, &p, 10);
+			if (*p == '>')
+				p++;
+			if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
+				pri = (LOG_USER | LOG_NOTICE);
+			
+			return pri;
+		}
+	}
+	
+	return 0;
+}
+
+#endif
+
+
 static void quit_signal(int sig)
 {
 	timestamp_and_log_internal("syslogd exiting");
@@ -550,7 +742,11 @@
 	char *last_buf;
 	char *recvbuf = G.recvbuf;
 #else
-#define recvbuf (G.recvbuf)
+	#if ENABLE_SYSLOG_CLASS
+	char *recvbuf = G.recvbuf;
+	#else
+	#define recvbuf (G.recvbuf)
+	#endif
 #endif
 
 	/* Set up signal handlers */
@@ -576,12 +772,20 @@
 	for (;;) {
 		ssize_t sz;
 
-#if ENABLE_FEATURE_SYSLOGD_DUP
+#if ENABLE_SYSLOG_CLASS
+	#if ENABLE_FEATURE_SYSLOGD_DUP==0
+		recvbuf = G.recvbuf + MAX_HEAD_ROOM;
+	#else
+		#error
+	#endif
+#else
+	#if ENABLE_FEATURE_SYSLOGD_DUP
 		last_buf = recvbuf;
 		if (recvbuf == G.recvbuf)
 			recvbuf = G.recvbuf + MAX_READ;
 		else
 			recvbuf = G.recvbuf;
+	#endif
 #endif
  read_again:
 		sz = safe_read(sock_fd, recvbuf, MAX_READ - 1);
@@ -609,10 +813,18 @@
 				continue;
 		last_sz = sz;
 #endif
+
+		/* Put local log processing before remote log because we would change buffer contents. --- Fanny*/
+		if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
+			recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */
+			split_escape_and_log(recvbuf, sz);
+		}
+
 #if ENABLE_FEATURE_REMOTE_LOG
 		/* We are not modifying log messages in any way before send */
 		/* Remote site cannot trust _us_ anyway and need to do validation again */
 		if (G.remoteAddrStr) {
+			int level = 0;
 			if (-1 == G.remoteFD) {
 				G.remoteFD = try_to_resolve_remote();
 				if (-1 == G.remoteFD)
@@ -624,15 +836,26 @@
 			/* send message to remote logger, ignore possible error */
 			/* TODO: on some errors, close and set G.remoteFD to -1
 			 * so that DNS resolution and connect is retried? */
-			sendto(G.remoteFD, recvbuf, sz+1, MSG_DONTWAIT,
-				    &G.remoteAddr->u.sa, G.remoteAddr->len);
+	#if ENABLE_SYSLOG_CLASS // fanny -- syslog classification
+			level = parse_log_level(recvbuf, sz); // yes, classify syslog
+			if (LOG_PRI(level) < G.logLevel){
+				if(tx_syslog_buf != recvbuf){
+					sendto(G.remoteFD, tx_syslog_buf, sz+2, MSG_DONTWAIT,
+						&G.remoteAddr->u.sa, G.remoteAddr->len); // transmit one more byte data
+				}else{
+					sendto(G.remoteFD, tx_syslog_buf, sz+1, MSG_DONTWAIT,
+						&G.remoteAddr->u.sa, G.remoteAddr->len); // original data
+				}
+			}
+	#else
+			level = parse_log_level(recvbuf, sz); 
+			if (LOG_PRI(level) < G.logLevel)
+				sendto(G.remoteFD, recvbuf, sz+1, MSG_DONTWAIT,
+				    	&G.remoteAddr->u.sa, G.remoteAddr->len);
+	#endif
  no_luck: ;
 		}
 #endif
-		if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
-			recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */
-			split_escape_and_log(recvbuf, sz);
-		}
 	} /* for (;;) */
 #undef recvbuf
 }
