M7350v7_en_gpl
This commit is contained in:
22
wlan/8192es/DriverSrcPkg/Users/mini_upnp/Android.mk
Executable file
22
wlan/8192es/DriverSrcPkg/Users/mini_upnp/Android.mk
Executable file
@ -0,0 +1,22 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
#########################
|
||||
|
||||
SOURCES = minixml.c \
|
||||
upnphttp.c \
|
||||
upnpreplyparse.c \
|
||||
upnpsoap.c \
|
||||
mini_upnp.c
|
||||
|
||||
#########################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_SRC_FILES := $(SOURCES)
|
||||
LOCAL_MODULE := lib_mini_upnp
|
||||
LOCAL_CFLAGS := -Os -Wall -D__ANDROID__
|
||||
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/../include
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
95
wlan/8192es/DriverSrcPkg/Users/mini_upnp/Makefile
Executable file
95
wlan/8192es/DriverSrcPkg/Users/mini_upnp/Makefile
Executable file
@ -0,0 +1,95 @@
|
||||
# $Id: Makefile,v 1.2 2009/01/13 02:50:10 bradhuang Exp $
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .c
|
||||
.PHONY: clean all depend
|
||||
|
||||
LIBS =
|
||||
INCS = -I$(TOP_USERS_DIR)/include
|
||||
#CFLAGS = -g -O2 -Wall
|
||||
CFLAGS := -Os -Wall $(CFLAGS) $(INCS)
|
||||
CPPFLAGS = -I. -I.
|
||||
DEPEND = .depend
|
||||
LDFLAGS += -g -s
|
||||
|
||||
#CC = rsdk-linux-gcc
|
||||
#CC = $(CROSS_COMPILE)gcc
|
||||
|
||||
CPP = gcc -E
|
||||
#AR = rsdk-linux-ar
|
||||
#AR = $(CROSS_COMPILE)ar
|
||||
|
||||
SOURCES = minixml.c, upnphttp.c, upnpreplyparse.c, upnpsoap.c \
|
||||
mini_upnp.c
|
||||
OBJS = $(SOURCES:.c=.o)
|
||||
|
||||
UPNP_DAEMON = mini_upnpd
|
||||
|
||||
# For mini_upnp stand alone
|
||||
STATIC_LIB=1
|
||||
|
||||
ifeq ($(STATIC_LIB),1)
|
||||
########## Build Static Library ##################
|
||||
all: mini_upnp.a
|
||||
|
||||
UPNP_LIB = mini_upnp.a
|
||||
|
||||
mini_upnp.a: mini_upnp.o minixml.o upnphttp.o upnpreplyparse.o upnpsoap.o
|
||||
$(AR) rcs $@ mini_upnp.o minixml.o upnphttp.o upnpreplyparse.o upnpsoap.o
|
||||
|
||||
else
|
||||
########## Build Shared Library ##################
|
||||
all: $(UPNP_DAEMON) $(UPNP_LIB)
|
||||
|
||||
UPNP_LIB = mini_upnp.so
|
||||
|
||||
CFLAGS += -DUSE_SHARED_DAEMON
|
||||
|
||||
minixml.o: minixml.c
|
||||
$(CC) -c -o $@ -fpic $(CFLAGS) $(IFLAGS) $<
|
||||
|
||||
upnphttp.o: upnphttp.c
|
||||
$(CC) -c -o $@ -fpic $(CFLAGS) $(IFLAGS) $<
|
||||
|
||||
upnpreplyparse.o: upnpreplyparse.c
|
||||
$(CC) -c -o $@ -fpic $(CFLAGS) $(IFLAGS) $<
|
||||
|
||||
upnpsoap.o: upnpsoap.c
|
||||
$(CC) -c -o $@ -fpic $(CFLAGS) $(IFLAGS) $<
|
||||
|
||||
$(UPNP_LIB): minixml.o upnphttp.o upnpreplyparse.o upnpsoap.o
|
||||
$(CC) -s -shared -o $@ minixml.o upnphttp.o upnpreplyparse.o upnpsoap.o
|
||||
|
||||
$(UPNP_DAEMON): mini_upnp.o $(UPNP_LIB)
|
||||
$(CC) -o $@ $(APMIB_LIB) $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
endif
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *.a $(UPNP_DAEMON)
|
||||
|
||||
romfs:
|
||||
ifeq ($(STATIC_LIB),1)
|
||||
@echo "Do nothing here."
|
||||
else
|
||||
$(ROMFSINST) mini_upnpd /bin/mini_upnpd
|
||||
$(ROMFSINST) mini_upnp.so /lib/mini_upnp.so
|
||||
endif
|
||||
|
||||
# depend stuff
|
||||
depend: $(SOURCES)
|
||||
$(CPP) $(CPPFLAGS) -MM $^ > $(DEPEND)
|
||||
|
||||
-include $(DEPEND)
|
||||
|
||||
# tags
|
||||
tags: $(SOURCES)
|
||||
ctags -o tags $^ *.h
|
||||
|
||||
.c.o:
|
||||
$(CC) -c -o $@ $(CFLAGS) $(IFLAGS) $<
|
||||
|
||||
|
||||
|
||||
|
964
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp.c
Executable file
964
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp.c
Executable file
@ -0,0 +1,964 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
/* for BSD's sysctl */
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include "upnphttp.h"
|
||||
#include "mini_upnp.h"
|
||||
#include "upnpreplyparse.h"
|
||||
|
||||
/* ip et port pour le SSDP */
|
||||
static int ssdpPort=1900;//#define PORT (1900)
|
||||
#define UPNP_MCAST_ADDR ("239.255.255.250")
|
||||
|
||||
#ifdef USE_SHARED_DAEMON
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if 0
|
||||
#define DEBUG_PRINT(fmt, args...) printf(fmt, ## args)
|
||||
#else
|
||||
#define DEBUG_PRINT(fmt, args...)
|
||||
#endif
|
||||
|
||||
|
||||
static daemon_CTX_Tp pGlobalCtx;
|
||||
|
||||
static char *Get_start(const unsigned long addr)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
pos = (char *)addr;
|
||||
while (*pos == ' ' || *pos == '\r' || *pos == '\n')
|
||||
pos++;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static char *Get_end(const unsigned long addr)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
pos = (char *)addr;
|
||||
while (*pos != ' ' && *pos != '\r' && *pos != '\n')
|
||||
pos++;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int parse_ssdp_file(const char *line, const int len, device_CTX_Tp device)
|
||||
{
|
||||
unsigned long string_begin=0;
|
||||
unsigned long string_end=0;
|
||||
unsigned long file_end=0;
|
||||
unsigned long file_pos=0;
|
||||
char tmp[10];
|
||||
unsigned char num_service=0;
|
||||
char *service_name;
|
||||
|
||||
if (line == NULL || len == 0 || device == NULL)
|
||||
return -1;
|
||||
|
||||
file_pos = (unsigned long) line;
|
||||
file_end = file_pos + len;
|
||||
|
||||
while (file_pos < file_end) {
|
||||
if (strncmp((char *)file_pos, "port", 4) == 0) {
|
||||
string_begin = (unsigned long)Get_start(file_pos+4);
|
||||
string_end = (unsigned long)Get_end(string_begin);
|
||||
if (string_end <= string_begin)
|
||||
return -1;
|
||||
memset(tmp, 0, 10);
|
||||
memcpy(tmp, (char *)string_begin, string_end - string_begin);
|
||||
device->port = atoi(tmp);
|
||||
file_pos = string_end;
|
||||
continue;
|
||||
}
|
||||
else if (strncmp((char *)file_pos, "max_age", 7) == 0) {
|
||||
string_begin = (unsigned long)Get_start(file_pos+7);
|
||||
string_end = (unsigned long)Get_end(string_begin);
|
||||
if (string_end <= string_begin)
|
||||
return -1;
|
||||
memset(tmp, 0, 10);
|
||||
memcpy(tmp, (char *)string_begin, string_end - string_begin);
|
||||
device->ctx.max_age = atoi(tmp);
|
||||
device->ctx.alive_timeout = device->ctx.max_age / 2;
|
||||
file_pos = string_end;
|
||||
continue;
|
||||
}
|
||||
else if (strncmp((char *)file_pos, "uuid", 4) == 0) {
|
||||
string_begin = (unsigned long)Get_start(file_pos+4);
|
||||
string_end = (unsigned long)Get_end(string_begin);
|
||||
if (string_end <= string_begin)
|
||||
return -1;
|
||||
memcpy(device->ctx.uuid, (char *)string_begin, string_end - string_begin);
|
||||
file_pos = string_end;
|
||||
continue;
|
||||
}
|
||||
else if (strncmp((char *)file_pos, "root_desc_name", 14) == 0) {
|
||||
string_begin = (unsigned long)Get_start(file_pos+14);
|
||||
string_end = (unsigned long)Get_end(string_begin);
|
||||
if (string_end <= string_begin)
|
||||
return -1;
|
||||
memcpy(device->ctx.root_desc_name, (char *)string_begin, string_end - string_begin);
|
||||
file_pos = string_end;
|
||||
continue;
|
||||
}
|
||||
else if (strncmp((char *)file_pos, "known_service_types", 19) == 0) {
|
||||
string_begin = (unsigned long)Get_start(file_pos+19);
|
||||
string_end = (unsigned long)Get_end(string_begin);
|
||||
if (string_end <= string_begin)
|
||||
return -1;
|
||||
service_name = (char *) malloc(string_end - string_begin + 1);
|
||||
if (service_name == NULL) {
|
||||
int i;
|
||||
for (i=0; i < MAX_NUMBER_OF_Service; i++) {
|
||||
if (device->known_service_types[i])
|
||||
free(device->known_service_types[i]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
memset(service_name, 0, string_end - string_begin + 1);
|
||||
memcpy(service_name, (char *)string_begin, string_end - string_begin);
|
||||
device->known_service_types[num_service] = service_name;
|
||||
num_service++;
|
||||
file_pos = string_end;
|
||||
continue;
|
||||
}
|
||||
file_pos++;
|
||||
}
|
||||
|
||||
device->ctx.known_service_types = device->known_service_types;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int get_file(char *fname, device_CTX_Tp pDevCtx)
|
||||
{
|
||||
char *ssdp_file;
|
||||
int len, ret;
|
||||
|
||||
if ((ssdp_file = mini_UPnP_UploadXML(fname)) != NULL) {
|
||||
len = strlen(ssdp_file);
|
||||
ret = parse_ssdp_file(ssdp_file, len, pDevCtx);
|
||||
|
||||
free(ssdp_file);
|
||||
if (ret != -1)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argument(daemon_CTX_Tp pCtx, int argc, char *argv[])
|
||||
{
|
||||
int argNum=1;
|
||||
IPCon ipcon=NULL;
|
||||
char *wsc_file=NULL, *igd_file=NULL;
|
||||
int wait_time=5, is_ok;
|
||||
char wsc_file_old[200], igd_file_old[200];
|
||||
|
||||
while (argNum < argc) {
|
||||
if (!strcmp(argv[argNum], "-interface")) {
|
||||
if (++argNum >= argc)
|
||||
break;
|
||||
strcpy(pCtx->interfacename, argv[argNum]);
|
||||
}
|
||||
else if (!strcmp(argv[argNum], "-wsc")) {
|
||||
if (++argNum >= argc)
|
||||
break;
|
||||
if (pCtx->num_device >= MAX_NUMBER_OF_DEVICE) {
|
||||
printf("The max number of supported devices is %d!\n", MAX_NUMBER_OF_DEVICE);
|
||||
return -1;
|
||||
}
|
||||
wsc_file = argv[argNum];
|
||||
strcpy(wsc_file_old, wsc_file);
|
||||
strcat(wsc_file_old, ".old");
|
||||
}
|
||||
else if ( !strcmp(argv[argNum], "-igd")) {
|
||||
if (++argNum >= argc)
|
||||
break;
|
||||
if (pCtx->num_device >= MAX_NUMBER_OF_DEVICE) {
|
||||
printf("The max number of supported devices is %d!\n", MAX_NUMBER_OF_DEVICE);
|
||||
return -1;
|
||||
}
|
||||
igd_file = argv[argNum];
|
||||
strcpy(igd_file_old, igd_file);
|
||||
strcat(igd_file_old, ".old");
|
||||
}
|
||||
else if ( !strcmp(argv[argNum], "-daemon")) {
|
||||
pCtx->daemon = 1;
|
||||
}
|
||||
else if ( !strcmp(argv[argNum], "-p")) {
|
||||
if (++argNum >= argc)
|
||||
break;
|
||||
ssdpPort=atoi(argv[argNum]);
|
||||
if((ssdpPort<0)||(ssdpPort>65535))
|
||||
{
|
||||
printf("Wrong -p option: port number should be 0~65535!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
argNum++;
|
||||
}
|
||||
|
||||
while (wait_time-- > 0 && (wsc_file || igd_file)) {
|
||||
if (wsc_file) {
|
||||
is_ok = 0;
|
||||
if (!get_file(wsc_file, &pCtx->device[pCtx->num_device])) {
|
||||
if (get_file(wsc_file_old, &pCtx->device[pCtx->num_device]))
|
||||
is_ok = 2;
|
||||
}
|
||||
else {
|
||||
is_ok = 1;
|
||||
rename(wsc_file, wsc_file_old);
|
||||
}
|
||||
if (is_ok) {
|
||||
pCtx->device[pCtx->num_device].used = DEVICE_WSC;
|
||||
strcpy(pCtx->device[pCtx->num_device].SSDP_file_name, WSCD_BYEBYE_FILE);
|
||||
strcpy(pCtx->device[pCtx->num_device].input_file_name, wsc_file);
|
||||
DEBUG_PRINT("Mini_upnpd: Read file [%s] success!\n", ((is_ok == 1) ? wsc_file : wsc_file_old));
|
||||
pCtx->num_device++;
|
||||
wsc_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (igd_file) {
|
||||
is_ok = 0;
|
||||
if (!get_file(igd_file, &pCtx->device[pCtx->num_device])) {
|
||||
if (get_file(igd_file_old, &pCtx->device[pCtx->num_device]))
|
||||
is_ok = 2;
|
||||
}
|
||||
else {
|
||||
is_ok = 1;
|
||||
rename(igd_file, igd_file_old);
|
||||
}
|
||||
if (is_ok) {
|
||||
pCtx->device[pCtx->num_device].used = DEVICE_IGD;
|
||||
strcpy(pCtx->device[pCtx->num_device].SSDP_file_name, IGD_BYEBYE_FILE);
|
||||
strcpy(pCtx->device[pCtx->num_device].input_file_name, igd_file);
|
||||
DEBUG_PRINT("Mini_upnpd: Read file [%s] success!\n", ((is_ok == 1) ? igd_file : igd_file_old));
|
||||
pCtx->num_device++;
|
||||
igd_file = NULL;
|
||||
}
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (pCtx->interfacename[0] == 0) {
|
||||
strcpy(pCtx->interfacename, "bridge0");
|
||||
}
|
||||
|
||||
ipcon = IPCon_New(pCtx->interfacename);
|
||||
if (ipcon == NULL) {
|
||||
printf("Error in IPCon_New!\n");
|
||||
return -1;
|
||||
}
|
||||
strcpy(pCtx->lan_ip_address, IPCon_GetIpAddrByStr(ipcon));
|
||||
IPCon_Destroy(ipcon);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_resource(daemon_CTX_Tp pCtx)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i=0; i<MAX_NUMBER_OF_DEVICE; i++)
|
||||
for (j=0; j<MAX_NUMBER_OF_Service; j++) {
|
||||
if (pCtx->device[i].known_service_types[j])
|
||||
free(pCtx->device[i].known_service_types[j]);
|
||||
}
|
||||
if (pCtx->sudp >= 0)
|
||||
close(pCtx->sudp);
|
||||
if (pCtx->snotify >= 0)
|
||||
close(pCtx->snotify);
|
||||
free(pCtx);
|
||||
}
|
||||
|
||||
static void sigHandler_alarm(int signo) {
|
||||
daemon_CTX_Tp pCtx=pGlobalCtx;
|
||||
unsigned char device_num=0;
|
||||
FILE *fp = NULL;
|
||||
struct stat status;
|
||||
char tmpbuf[100];
|
||||
|
||||
for (device_num=0; device_num<MAX_NUMBER_OF_DEVICE; device_num++) {
|
||||
if (pCtx->device[device_num].used == 0)
|
||||
continue;
|
||||
|
||||
if (get_file(pCtx->device[device_num].input_file_name, &pCtx->device[device_num])) {
|
||||
DEBUG_PRINT("Mini_upnpd-Alarm: Read file [%s] success!\n", pCtx->device[device_num].input_file_name);
|
||||
// when wscd case ; don't send "bye-bye+alive " for fix windows7 IOT issue;
|
||||
if(strcmp(pCtx->device[device_num].input_file_name , (WIFI_WPS_TMP_DIR "/wscd_config")))
|
||||
{
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 1, 1);
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 0, pCtx->device[device_num].ctx.max_age);
|
||||
}
|
||||
strcpy(tmpbuf, pCtx->device[device_num].input_file_name);
|
||||
strcat(tmpbuf, ".old");
|
||||
rename(pCtx->device[device_num].input_file_name, tmpbuf);
|
||||
|
||||
}
|
||||
|
||||
if (pCtx->device[device_num].ctx.alive_timeout > 0 && --pCtx->device[device_num].ctx.alive_timeout <= 0) {
|
||||
//sending alive
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 0, pCtx->device[device_num].ctx.max_age);
|
||||
pCtx->device[device_num].ctx.alive_timeout = pCtx->device[device_num].ctx.max_age/2;
|
||||
}
|
||||
|
||||
//check whether the bye-bye file is there
|
||||
if (stat(pCtx->device[device_num].SSDP_file_name, &status) != 0)
|
||||
continue;
|
||||
|
||||
if ((fp = fopen(pCtx->device[device_num].SSDP_file_name, "r")) != NULL) {
|
||||
int event=0;
|
||||
unsigned char line[3];
|
||||
|
||||
memset(line, 0, 3);
|
||||
fgets(line, sizeof(line), fp);
|
||||
if (sscanf(line, "%d", &event)) {
|
||||
if (event == 1) {
|
||||
//sending byebye
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 1, 1);
|
||||
//syslog(LOG_INFO, "Sending bye bye...");
|
||||
DEBUG_PRINT("Sending bye bye...\n");
|
||||
|
||||
//sending alive
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 0, pCtx->device[device_num].ctx.max_age);
|
||||
//syslog(LOG_INFO, "Sending Advertisement...");
|
||||
DEBUG_PRINT("Sending Advertisement...\n");
|
||||
|
||||
pCtx->device[device_num].ctx.alive_timeout = pCtx->device[device_num].ctx.max_age/2;
|
||||
}
|
||||
else if (event == 2) {
|
||||
//sending byebye
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 1, 1);
|
||||
//syslog(LOG_INFO, "Sending bye bye...");
|
||||
DEBUG_PRINT("Sending bye bye...\n");
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
remove(pCtx->device[device_num].SSDP_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
alarm(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
daemon_CTX_Tp pCtx=NULL;
|
||||
unsigned char device_num=0;
|
||||
int selret;
|
||||
fd_set netFD;
|
||||
|
||||
/* Allocate context */
|
||||
pCtx = (daemon_CTX_Tp) calloc(1, sizeof(daemon_CTX_T));
|
||||
if (pCtx == NULL) {
|
||||
printf("allocate context failed!\n");
|
||||
return 0;
|
||||
}
|
||||
pGlobalCtx = pCtx;
|
||||
|
||||
pCtx->sudp = -1;
|
||||
pCtx->snotify = -1;
|
||||
|
||||
// sleep(3);
|
||||
if (parse_argument(pCtx, argc, argv) < 0) {
|
||||
printf("Parse argument failed!\n");
|
||||
free_resource(pCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCtx->num_device <= 0) {
|
||||
DEBUG_PRINT("Number of device is 0!\n");
|
||||
free_resource(pCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCtx->daemon) {
|
||||
if (daemon(0,1) == -1) {
|
||||
printf("fork mini_upnp daemon error!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
int openlog_option;
|
||||
int debug_flag = 1;
|
||||
openlog_option = LOG_PID|LOG_CONS;
|
||||
if(debug_flag)
|
||||
openlog_option |= LOG_PERROR; /* also log on stderr */
|
||||
openlog("mini_upnpd", openlog_option, LOG_USER/*LOG_LOCAL0*/);
|
||||
#endif
|
||||
|
||||
DEBUG_PRINT("Interface name : %s\n", pCtx->interfacename);
|
||||
DEBUG_PRINT("IP : %s\n", pCtx->lan_ip_address);
|
||||
DEBUG_PRINT("Number of devices : %d\n", pCtx->num_device);
|
||||
for (device_num=0; device_num<MAX_NUMBER_OF_DEVICE; device_num++) {
|
||||
if (pCtx->device[device_num].used) {
|
||||
DEBUG_PRINT("Device port : %d\n", pCtx->device[device_num].port);
|
||||
DEBUG_PRINT("\t%s\n", pCtx->device[device_num].ctx.uuid);
|
||||
DEBUG_PRINT("\tmax_age : %d\n", pCtx->device[device_num].ctx.max_age);
|
||||
DEBUG_PRINT("\troot_desc_name : %s\n", pCtx->device[device_num].ctx.root_desc_name);
|
||||
int i=0;
|
||||
while (pCtx->device[device_num].ctx.known_service_types[i]) {
|
||||
DEBUG_PRINT("\t%s%s\n", pCtx->device[device_num].ctx.known_service_types[i],
|
||||
(i==0?"":"1"));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* socket d'ecoute pour le SSDP */
|
||||
pCtx->sudp = OpenAndConfUdpSocket(pCtx->lan_ip_address);
|
||||
if (pCtx->sudp < 0)
|
||||
{
|
||||
printf("Failed to open socket for SSDP. EXITING\n");
|
||||
free_resource(pCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open socket for sending notifications */
|
||||
pCtx->snotify = OpenAndConfNotifySocket(pCtx->lan_ip_address);
|
||||
if (pCtx->snotify < 0)
|
||||
{
|
||||
printf("Failed to open socket for SSDP notify messages\n");
|
||||
free_resource(pCtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
signal(SIGALRM, sigHandler_alarm);
|
||||
|
||||
for (device_num=0; device_num<MAX_NUMBER_OF_DEVICE; device_num++) {
|
||||
//sending byebye
|
||||
if (pCtx->device[device_num].used)
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 1, 1);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
for (device_num=0; device_num<MAX_NUMBER_OF_DEVICE; device_num++) {
|
||||
//sending alive
|
||||
if (pCtx->device[device_num].used)
|
||||
SendSSDPNotifies(pCtx->snotify, pCtx->lan_ip_address, pCtx->device[device_num].port,
|
||||
&pCtx->device[device_num].ctx, 0, pCtx->device[device_num].ctx.max_age);
|
||||
}
|
||||
|
||||
/* Start one second timer */
|
||||
alarm(1);
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&netFD);
|
||||
if (pCtx->sudp >= 0)
|
||||
FD_SET(pCtx->sudp, &netFD);
|
||||
selret = select(pCtx->sudp+1, &netFD, NULL, NULL, NULL);
|
||||
if (selret >= 0) {
|
||||
if(pCtx->sudp >= 0 && FD_ISSET(pCtx->sudp, &netFD))
|
||||
{
|
||||
ProcessSSDPRequest(pCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int AddMulticastMembership(int s, const char * ifaddr)
|
||||
{
|
||||
struct ip_mreq imr; /* Ip multicast membership */
|
||||
|
||||
/* setting up imr structure */
|
||||
imr.imr_multiaddr.s_addr = inet_addr(UPNP_MCAST_ADDR);
|
||||
/*imr.imr_interface.s_addr = htonl(INADDR_ANY);*/
|
||||
imr.imr_interface.s_addr = inet_addr(ifaddr);
|
||||
|
||||
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&imr, sizeof(struct ip_mreq)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp, IP_ADD_MEMBERSHIP): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OpenAndConfUdpSocket(const char * ifaddr)
|
||||
{
|
||||
int s, onOff=1;
|
||||
struct sockaddr_in sockname;
|
||||
|
||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "socket(udp): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&onOff, sizeof(onOff) ) != 0 ) {
|
||||
syslog(LOG_ERR, "setsockopt(udp): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_port = htons(ssdpPort);//PORT=>ssdpPort
|
||||
/* NOTE : it seems it doesnt work when binding on the specific address */
|
||||
/*sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);*/
|
||||
sockname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
/*sockname.sin_addr.s_addr = inet_addr(ifaddr);*/
|
||||
|
||||
if(bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "bind(udp): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(AddMulticastMembership(s, ifaddr) < 0)
|
||||
{
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* open the UDP socket used to send SSDP notifications to
|
||||
* the multicast group reserved for them */
|
||||
int OpenAndConfNotifySocket(const char * addr)
|
||||
{
|
||||
int s;
|
||||
unsigned char loopchar = 0;
|
||||
struct in_addr mc_if;
|
||||
struct sockaddr_in sockname;
|
||||
|
||||
if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "socket(udp_notify): %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mc_if.s_addr = inet_addr(addr);
|
||||
|
||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopchar, sizeof(loopchar)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_LOOP): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char *)&mc_if, sizeof(mc_if)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "setsockopt(udp_notify, IP_MULTICAST_IF): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "bind(udp_notify): %m");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* response from a LiveBox (Wanadoo)
|
||||
HTTP/1.1 200 OK
|
||||
CACHE-CONTROL: max-age=1800
|
||||
DATE: Thu, 01 Jan 1970 04:03:23 GMT
|
||||
EXT:
|
||||
LOCATION: http://192.168.0.1:49152/gatedesc.xml
|
||||
SERVER: Linux/2.4.17, UPnP/1.0, Intel SDK for UPnP devices /1.2
|
||||
ST: upnp:rootdevice
|
||||
USN: uuid:75802409-bccb-40e7-8e6c-fa095ecce13e::upnp:rootdevice
|
||||
|
||||
* response from a Linksys 802.11b :
|
||||
HTTP/1.1 200 OK
|
||||
Cache-Control:max-age=120
|
||||
Location:http://192.168.5.1:5678/rootDesc.xml
|
||||
Server:NT/5.0 UPnP/1.0
|
||||
ST:upnp:rootdevice
|
||||
USN:uuid:upnp-InternetGatewayDevice-1_0-0090a2777777::upnp:rootdevice
|
||||
EXT:
|
||||
*/
|
||||
|
||||
/* not really an SSDP "announce" as it is the response
|
||||
* to a SSDP "M-SEARCH" */
|
||||
void SendSSDPAnnounce2(int s, struct sockaddr_in sockname,
|
||||
const char * st, int st_len,
|
||||
const char * host, unsigned short port,
|
||||
SSDP_CTX_Tp SSDP)
|
||||
{
|
||||
int l, n;
|
||||
char *buf=NULL;
|
||||
/* TODO :
|
||||
* follow guideline from document "UPnP Device Architecture 1.0"
|
||||
* put in uppercase.
|
||||
* DATE: is recommended
|
||||
* SERVER: OS/ver UPnP/1.0 miniupnpd/1.0
|
||||
* */
|
||||
if (st == NULL || host == NULL || SSDP == NULL)
|
||||
return;
|
||||
|
||||
buf = (char *) malloc(512);
|
||||
if (buf == NULL) {
|
||||
syslog(LOG_ERR, "SendSSDPAnnounce2: out of memory!");
|
||||
return;
|
||||
}
|
||||
memset(buf, 0, 512);
|
||||
|
||||
/*CVE-2021-35392*/
|
||||
//l = sprintf(buf,
|
||||
l = snprintf(buf,512,
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Cache-Control: max-age=%d\r\n"
|
||||
"ST: %.*s\r\n"
|
||||
"USN: %s::%.*s\r\n"
|
||||
"EXT:\r\n"
|
||||
"Server: " MINIUPNPD_SERVER_STRING "\r\n"
|
||||
"Location: http://%s:%u/%s.xml" "\r\n"
|
||||
"\r\n",
|
||||
SSDP->max_age,
|
||||
st_len, st,
|
||||
SSDP->uuid, st_len, st,
|
||||
host, (unsigned int)port, SSDP->root_desc_name);
|
||||
n = sendto(s, buf, l, 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "sendto: %m");
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
// type = 0 (alive); type = 1 (byebye)
|
||||
void SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
SSDP_CTX_Tp SSDP,
|
||||
unsigned char type, unsigned int max_age)
|
||||
{
|
||||
struct sockaddr_in sockname;
|
||||
int n, i, j;
|
||||
char *bufr=NULL;
|
||||
|
||||
if (host == NULL || SSDP->root_desc_name == NULL || SSDP->uuid == NULL ||
|
||||
SSDP->known_service_types == NULL)
|
||||
return;
|
||||
|
||||
bufr = (char *) malloc(512);
|
||||
if (bufr == NULL) {
|
||||
syslog(LOG_ERR, "SendSSDPNotifies: out of memory!");
|
||||
return;
|
||||
}
|
||||
memset(bufr, 0, 512);
|
||||
|
||||
memset(&sockname, 0, sizeof(struct sockaddr_in));
|
||||
sockname.sin_family = AF_INET;
|
||||
sockname.sin_port = htons(ssdpPort);//PORT=>ssdpPort
|
||||
sockname.sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
|
||||
|
||||
for (j=0; j <2; j++) {
|
||||
i = 0;
|
||||
while(SSDP->known_service_types[i])
|
||||
{
|
||||
if (i == 1) {
|
||||
snprintf(bufr,512, \
|
||||
"NOTIFY * HTTP/1.1\r\n"
|
||||
"Host:%s:%d\r\n"
|
||||
"Cache-Control:max-age=%d\r\n"
|
||||
"Location:http://%s:%d/%s.xml" "\r\n"
|
||||
"Server:" MINIUPNPD_SERVER_STRING "\r\n"
|
||||
"NT:%s\r\n"
|
||||
"USN:%s\r\n"
|
||||
"NTS:ssdp:%s\r\n"
|
||||
"\r\n",
|
||||
UPNP_MCAST_ADDR, ssdpPort, max_age,//PORT=>ssdpPort
|
||||
host, port, SSDP->root_desc_name,
|
||||
SSDP->uuid,
|
||||
SSDP->uuid,
|
||||
(type==0?"alive":"byebye"));
|
||||
n = sendto(s, bufr, strlen(bufr), 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "sendto: %m");
|
||||
}
|
||||
}
|
||||
snprintf(bufr,512, \
|
||||
"NOTIFY * HTTP/1.1\r\n"
|
||||
"Host:%s:%d\r\n"
|
||||
"Cache-Control:max-age=%d\r\n"
|
||||
"Location:http://%s:%d/%s.xml" "\r\n"
|
||||
"Server:" MINIUPNPD_SERVER_STRING "\r\n"
|
||||
"NT:%s%s\r\n"
|
||||
"USN:%s::%s%s\r\n"
|
||||
"NTS:ssdp:%s\r\n"
|
||||
"\r\n",
|
||||
UPNP_MCAST_ADDR, ssdpPort, max_age,//PORT=>ssdpPort
|
||||
host, port, SSDP->root_desc_name,
|
||||
SSDP->known_service_types[i], (i==0?"":"1"),
|
||||
SSDP->uuid, SSDP->known_service_types[i], (i==0?"":"1"),
|
||||
(type==0?"alive":"byebye"));
|
||||
n = sendto(s, bufr, strlen(bufr), 0,
|
||||
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in) );
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "sendto: %m");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
free(bufr);
|
||||
}
|
||||
|
||||
#ifdef USE_SHARED_DAEMON
|
||||
void ProcessSSDPRequest(daemon_CTX_Tp pCtx)
|
||||
{
|
||||
int n;
|
||||
char *bufr=NULL;
|
||||
socklen_t len_r;
|
||||
struct sockaddr_in sendername;
|
||||
int i, l, j;
|
||||
char * st = 0;
|
||||
int st_len = 0;
|
||||
|
||||
if (pCtx == NULL)
|
||||
return;
|
||||
|
||||
bufr = (char *) malloc(2048);
|
||||
if (bufr == NULL) {
|
||||
syslog(LOG_ERR, "ProcessSSDPRequest: out of memory!");
|
||||
return;
|
||||
}
|
||||
memset(bufr, 0, 2048);
|
||||
|
||||
len_r = sizeof(struct sockaddr_in);
|
||||
n = recvfrom(pCtx->sudp, bufr, 2048, 0,
|
||||
(struct sockaddr *)&sendername, &len_r);
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "recvfrom: %m");
|
||||
free(bufr);
|
||||
return;
|
||||
}
|
||||
if(memcmp(bufr, "NOTIFY", 6) == 0)
|
||||
{
|
||||
/* ignore NOTIFY packets. We could log the sender and device type */
|
||||
free(bufr);
|
||||
return;
|
||||
}
|
||||
else if(memcmp(bufr, "M-SEARCH", 8) == 0)
|
||||
{
|
||||
i = 0;
|
||||
while(i<n)
|
||||
{
|
||||
while(bufr[i] != '\r' || bufr[i+1] != '\n')
|
||||
i++;
|
||||
i += 2;
|
||||
if(strncasecmp(bufr+i, "st:", 3) == 0)
|
||||
{
|
||||
st = bufr+i+3;
|
||||
st_len = 0;
|
||||
while(*st == ' ' || *st == '\t') st++;
|
||||
while(st[st_len]!='\r' && st[st_len]!='\n') st_len++;
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
/*j = 0;*/
|
||||
/*while(bufr[i+j]!='\r') j++;*/
|
||||
/*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
|
||||
}
|
||||
}
|
||||
/*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );*/
|
||||
if(st)
|
||||
{
|
||||
for (j=0; j<MAX_NUMBER_OF_DEVICE; j++) {
|
||||
if (pCtx->device[j].used) {
|
||||
i = 0;
|
||||
while(pCtx->device[j].known_service_types[i])
|
||||
{
|
||||
l = (int)strlen(pCtx->device[j].known_service_types[i]);
|
||||
if(l<=st_len && (0 == memcmp(st, pCtx->device[j].known_service_types[i], l)))
|
||||
{
|
||||
/* TODO : doesnt answer at once but wait for a random time */
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port),
|
||||
st_len, st);
|
||||
|
||||
SendSSDPAnnounce2(pCtx->sudp, sendername, st, st_len, pCtx->lan_ip_address, pCtx->device[j].port,
|
||||
&pCtx->device[j].ctx);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
l = (int)strlen(pCtx->device[j].ctx.uuid);
|
||||
if(l==st_len && (0 == memcmp(st, pCtx->device[j].ctx.uuid, l)))
|
||||
{
|
||||
/* TODO : doesnt answer at once but wait for a random time */
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port),
|
||||
st_len, st);
|
||||
SendSSDPAnnounce2(pCtx->sudp, sendername, st, st_len, pCtx->lan_ip_address, pCtx->device[j].port,
|
||||
&pCtx->device[j].ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_INFO, "invalid SSDP M-SEARCH from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );
|
||||
}
|
||||
|
||||
free(bufr);
|
||||
}
|
||||
#else
|
||||
void ProcessSSDPRequest(int s, const char * host, unsigned short port,
|
||||
SSDP_CTX_Tp SSDP)
|
||||
{
|
||||
int n;
|
||||
char *bufr=NULL;
|
||||
socklen_t len_r;
|
||||
struct sockaddr_in sendername;
|
||||
int i, l;
|
||||
char * st = 0;
|
||||
int st_len = 0;
|
||||
|
||||
if (SSDP == NULL || host == NULL)
|
||||
return;
|
||||
|
||||
bufr = (char *) malloc(2048);
|
||||
if (bufr == NULL) {
|
||||
syslog(LOG_ERR, "ProcessSSDPRequest: out of memory!");
|
||||
return;
|
||||
}
|
||||
memset(bufr, 0, 2048);
|
||||
|
||||
len_r = sizeof(struct sockaddr_in);
|
||||
n = recvfrom(s, bufr, 2048, 0,
|
||||
(struct sockaddr *)&sendername, &len_r);
|
||||
if(n<0)
|
||||
{
|
||||
syslog(LOG_ERR, "recvfrom: %m");
|
||||
free(bufr);
|
||||
return;
|
||||
}
|
||||
if(memcmp(bufr, "NOTIFY", 6) == 0)
|
||||
{
|
||||
/* ignore NOTIFY packets. We could log the sender and device type */
|
||||
free(bufr);
|
||||
return;
|
||||
}
|
||||
else if(memcmp(bufr, "M-SEARCH", 8) == 0)
|
||||
{
|
||||
i = 0;
|
||||
while(i<n)
|
||||
{
|
||||
while(bufr[i] != '\r' || bufr[i+1] != '\n')
|
||||
i++;
|
||||
i += 2;
|
||||
if(strncasecmp(bufr+i, "st:", 3) == 0)
|
||||
{
|
||||
st = bufr+i+3;
|
||||
st_len = 0;
|
||||
while(*st == ' ' || *st == '\t') st++;
|
||||
while(st[st_len]!='\r' && st[st_len]!='\n') st_len++;
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
/*j = 0;*/
|
||||
/*while(bufr[i+j]!='\r') j++;*/
|
||||
/*syslog(LOG_INFO, "%.*s", j, bufr+i);*/
|
||||
}
|
||||
}
|
||||
/*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );*/
|
||||
if(st)
|
||||
{
|
||||
i = 0;
|
||||
while(SSDP->known_service_types[i])
|
||||
{
|
||||
l = (int)strlen(SSDP->known_service_types[i]);
|
||||
if(l<=st_len && (0 == memcmp(st, SSDP->known_service_types[i], l)))
|
||||
{
|
||||
/* TODO : doesnt answer at once but wait for a random time */
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port),
|
||||
st_len, st);
|
||||
SendSSDPAnnounce2(s, sendername, st, st_len, host, port,
|
||||
SSDP);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
l = (int)strlen(SSDP->uuid);
|
||||
if(l==st_len && (0 == memcmp(st, SSDP->uuid, l)))
|
||||
{
|
||||
/* TODO : doesnt answer at once but wait for a random time */
|
||||
/*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/
|
||||
syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port),
|
||||
st_len, st);
|
||||
SendSSDPAnnounce2(s, sendername, st, st_len, host, port,
|
||||
SSDP);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_INFO, "invalid SSDP M-SEARCH from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d",
|
||||
inet_ntoa(sendername.sin_addr),
|
||||
ntohs(sendername.sin_port) );
|
||||
}
|
||||
|
||||
free(bufr);
|
||||
}
|
||||
#endif
|
||||
|
78
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp.h
Executable file
78
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp.h
Executable file
@ -0,0 +1,78 @@
|
||||
#ifndef MINI_UPNP_H
|
||||
#define MINI_UPNP_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "mini_upnp_global.h"
|
||||
#include "upnphttp.h"
|
||||
|
||||
#include "rtk_arch.h"
|
||||
|
||||
typedef struct SSDP_context {
|
||||
char **known_service_types;
|
||||
char root_desc_name[100];
|
||||
char uuid[42];
|
||||
unsigned int max_age;
|
||||
unsigned int alive_timeout;
|
||||
} SSDP_CTX_T, *SSDP_CTX_Tp;
|
||||
|
||||
#ifdef USE_SHARED_DAEMON
|
||||
#define MAX_NUMBER_OF_DEVICE 2
|
||||
#define MAX_NUMBER_OF_Service 10
|
||||
#define WSCD_BYEBYE_FILE (WIFI_WPS_TMP_DIR "/wscd_byebye")
|
||||
#define IGD_BYEBYE_FILE ("/tmp/igd_byebye")
|
||||
|
||||
enum { DEVICE_UNUSED=0, DEVICE_IGD=1, DEVICE_WSC=2 };
|
||||
|
||||
typedef struct device_context {
|
||||
unsigned char used;
|
||||
int port;
|
||||
char SSDP_file_name[30];
|
||||
SSDP_CTX_T ctx;
|
||||
char *known_service_types[MAX_NUMBER_OF_Service];
|
||||
char input_file_name[40];
|
||||
} device_CTX_T, *device_CTX_Tp;
|
||||
|
||||
typedef struct daemon_context {
|
||||
char lan_ip_address[IP_ADDRLEN];
|
||||
char interfacename[20];
|
||||
unsigned char num_device;
|
||||
device_CTX_T device[MAX_NUMBER_OF_DEVICE];
|
||||
int sudp;
|
||||
int snotify;
|
||||
int daemon; // run as daemon
|
||||
} daemon_CTX_T, *daemon_CTX_Tp;
|
||||
#endif
|
||||
|
||||
typedef struct mini_upnp_context {
|
||||
LIST_HEAD(httplisthead, upnphttp) upnphttphead;
|
||||
SSDP_CTX_T SSDP;
|
||||
char lan_ip_address[IP_ADDRLEN];
|
||||
struct _soapMethods *soapMethods;
|
||||
struct _sendDesc *sendDesc;
|
||||
struct upnp_subscription_record subscribe_list;
|
||||
int port;
|
||||
int sudp;
|
||||
int shttpl;
|
||||
int snotify;
|
||||
char *rootXML;
|
||||
unsigned int rootXML_len;
|
||||
char *serviceXML;
|
||||
unsigned int serviceXML_len;
|
||||
} mini_upnp_CTX_T, *mini_upnp_CTX_Tp;
|
||||
|
||||
extern int OpenAndConfUdpSocket(const char * ifaddr);
|
||||
extern int OpenAndConfNotifySocket(const char * addr);
|
||||
extern void SendSSDPAnnounce2(int s, struct sockaddr_in sockname,
|
||||
const char * st, int st_len,
|
||||
const char * host, unsigned short port,
|
||||
SSDP_CTX_Tp SSDP);
|
||||
extern void SendSSDPNotifies(int s, const char * host, unsigned short port,
|
||||
SSDP_CTX_Tp SSDP,
|
||||
unsigned char type, unsigned int max_age);
|
||||
#ifdef USE_SHARED_DAEMON
|
||||
extern void ProcessSSDPRequest(daemon_CTX_Tp pCtx);
|
||||
#else
|
||||
extern void ProcessSSDPRequest(int s, const char * host, unsigned short port, SSDP_CTX_Tp SSDP);
|
||||
#endif
|
||||
#endif
|
18
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp_global.h
Executable file
18
wlan/8192es/DriverSrcPkg/Users/mini_upnp/mini_upnp_global.h
Executable file
@ -0,0 +1,18 @@
|
||||
#ifndef _MINI_UPNP_GLOBAL_H
|
||||
#define _MINI_UPNP_GLOBAL_H
|
||||
|
||||
/* Server: HTTP header returned in all HTTP responses : */
|
||||
#define MINIUPNPD_SERVER_STRING "OS 1.0 UPnP/1.0 Realtek/V1.3"
|
||||
|
||||
#define IP_ADDRLEN 17
|
||||
#define SID_LEN 44
|
||||
#define URL_MAX_LEN 200
|
||||
#define IP_V4_DOT_COUNT 3
|
||||
#define MAX_SUB_TIMEOUT 7200
|
||||
|
||||
#define BOOLEAN char
|
||||
#define TRUE (1==1)
|
||||
#define FALSE (1==0)
|
||||
|
||||
#define syslog(x, fmt, args...);
|
||||
#endif
|
160
wlan/8192es/DriverSrcPkg/Users/mini_upnp/minixml.c
Executable file
160
wlan/8192es/DriverSrcPkg/Users/mini_upnp/minixml.c
Executable file
@ -0,0 +1,160 @@
|
||||
|
||||
#include "minixml.h"
|
||||
|
||||
/* parseatt : used to parse the argument list
|
||||
* return 0 (false) in case of success and -1 (true) if the end
|
||||
* of the xmlbuffer is reached. */
|
||||
int parseatt(struct xmlparser * p)
|
||||
{
|
||||
const char * attname;
|
||||
int attnamelen;
|
||||
const char * attvalue;
|
||||
int attvaluelen;
|
||||
while(p->xml < p->xmlend)
|
||||
{
|
||||
if(*p->xml=='/' || *p->xml=='>')
|
||||
return 0;
|
||||
if( !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
char sep;
|
||||
attname = p->xml;
|
||||
attnamelen = 0;
|
||||
while(*p->xml!='=' && !IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
attnamelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(*(p->xml++) != '=')
|
||||
{
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
while(IS_WHITE_SPACE(*p->xml))
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
sep = *p->xml;
|
||||
if(sep=='\'' || sep=='\"')
|
||||
{
|
||||
p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while(*p->xml != sep)
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
attvalue = p->xml;
|
||||
attvaluelen = 0;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& *p->xml != '>' && *p->xml != '/')
|
||||
{
|
||||
attvaluelen++; p->xml++;
|
||||
if(p->xml >= p->xmlend)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/*printf("%.*s='%.*s'\n",
|
||||
attnamelen, attname, attvaluelen, attvalue);*/
|
||||
if(p->attfunc)
|
||||
p->attfunc(p->data, attname, attnamelen, attvalue, attvaluelen);
|
||||
}
|
||||
p->xml++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parseelt parse the xml stream and
|
||||
* call the callback functions when needed... */
|
||||
void parseelt(struct xmlparser * p)
|
||||
{
|
||||
int i;
|
||||
const char * elementname;
|
||||
while(p->xml < (p->xmlend - 1))
|
||||
{
|
||||
if((p->xml)[0]=='<' && (p->xml)[1]!='?')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
while( !IS_WHITE_SPACE(*p->xml)
|
||||
&& (*p->xml!='>') && (*p->xml!='/')
|
||||
)
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
/* to ignore namespace : */
|
||||
if(*p->xml==':')
|
||||
{
|
||||
i = 0;
|
||||
elementname = ++p->xml;
|
||||
}
|
||||
}
|
||||
if(i>0)
|
||||
{
|
||||
if(p->starteltfunc)
|
||||
p->starteltfunc(p->data, elementname, i);
|
||||
if(parseatt(p))
|
||||
return;
|
||||
if(*p->xml!='/')
|
||||
{
|
||||
const char * data;
|
||||
i = 0; data = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while( IS_WHITE_SPACE(*p->xml) )
|
||||
{
|
||||
i++; p->xml++; // support HNAP1
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
while(*p->xml!='<')
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(i>0 && p->datafunc)
|
||||
p->datafunc(p->data, data, i);
|
||||
}
|
||||
}
|
||||
else if(*p->xml == '/')
|
||||
{
|
||||
i = 0; elementname = ++p->xml;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
while((*p->xml != '>'))
|
||||
{
|
||||
i++; p->xml++;
|
||||
if (p->xml >= p->xmlend)
|
||||
return;
|
||||
}
|
||||
if(p->endeltfunc)
|
||||
p->endeltfunc(p->data, elementname, i);
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->xml++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the parser must be initialized before calling this function */
|
||||
void parsexml(struct xmlparser * parser)
|
||||
{
|
||||
parser->xml = parser->xmlstart;
|
||||
parser->xmlend = parser->xmlstart + parser->xmlsize;
|
||||
parseelt(parser);
|
||||
}
|
||||
|
||||
|
37
wlan/8192es/DriverSrcPkg/Users/mini_upnp/minixml.h
Executable file
37
wlan/8192es/DriverSrcPkg/Users/mini_upnp/minixml.h
Executable file
@ -0,0 +1,37 @@
|
||||
/* $Id: minixml.h,v 1.1.1.1 2007/08/06 10:04:43 root Exp $ */
|
||||
/* minimal xml parser
|
||||
*
|
||||
* Project : miniupnp
|
||||
* Website : http://miniupnp.free.fr/
|
||||
* Author : Thomas Bernard
|
||||
* Copyright (c) 2005 Thomas Bernard
|
||||
* This software is subject to the conditions detailed in the
|
||||
* LICENCE file provided in this distribution.
|
||||
* */
|
||||
#ifndef __MINIXML_H__
|
||||
#define __MINIXML_H__
|
||||
#define IS_WHITE_SPACE(c) ((c==' ') || (c=='\t') || (c=='\r') || (c=='\n'))
|
||||
|
||||
/* if a callback function pointer is set to NULL,
|
||||
* the function is not called */
|
||||
struct xmlparser {
|
||||
const char *xmlstart;
|
||||
const char *xmlend;
|
||||
const char *xml; /* pointer to current character */
|
||||
int xmlsize;
|
||||
void * data;
|
||||
void (*starteltfunc) (void *, const char *, int);
|
||||
void (*endeltfunc) (void *, const char *, int);
|
||||
void (*datafunc) (void *, const char *, int);
|
||||
void (*attfunc) (void *, const char *, int, const char *, int);
|
||||
};
|
||||
|
||||
/* parsexml()
|
||||
* the xmlparser structure must be initialized before the call
|
||||
* the following structure members have to be initialized :
|
||||
* xmlstart, xmlsize, data, *func
|
||||
* xml is for internal usage, xmlend is computed automatically */
|
||||
void parsexml(struct xmlparser *);
|
||||
|
||||
#endif
|
||||
|
1823
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnphttp.c
Executable file
1823
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnphttp.c
Executable file
File diff suppressed because it is too large
Load Diff
212
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnphttp.h
Executable file
212
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnphttp.h
Executable file
@ -0,0 +1,212 @@
|
||||
#ifndef __UPNPHTTP_H__
|
||||
#define __UPNPHTTP_H__
|
||||
#include <sys/queue.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "mini_upnp_global.h"
|
||||
|
||||
/** @name UPNP_E_SUCCESS [0]
|
||||
* {\tt UPNP_E_SUCCESS} signifies that the operation completed successfully.
|
||||
* For asynchronous functions, this only means that the packet generated by
|
||||
* the operation was successfully transmitted on the network. The result of
|
||||
* the entire operation comes as part of the callback for that operation.
|
||||
*/
|
||||
//@{
|
||||
#define UPNP_E_SUCCESS 0
|
||||
//@}
|
||||
|
||||
/** @name UPNP_E_INVALID_PARAM [-101]
|
||||
* {\tt UPNP_E_INVALID_PARAM} signifies that one or more of the parameters
|
||||
* passed to the function is not valid. Refer to the documentation for each
|
||||
* function for more information on the valid ranges of the parameters.
|
||||
*/
|
||||
//@{
|
||||
#define UPNP_E_INVALID_PARAM -101
|
||||
//@}
|
||||
|
||||
/** @name UPNP_E_OUTOF_MEMORY [-104]
|
||||
* {\tt UPNP_E_OUTOF_MEMORY} signifies that not enough resources are
|
||||
* currently available to complete the operation. Most operations require
|
||||
* some free memory in order to complete their work.
|
||||
*/
|
||||
//@{
|
||||
#define UPNP_E_OUTOF_MEMORY -102
|
||||
//@}
|
||||
|
||||
#define UPNP_E_TOOMANY_SUBSCRIBERS -103
|
||||
|
||||
/* event ID */
|
||||
#define UPNP_EVENT_SUBSCRIPTION_REQUEST 1
|
||||
#define UPNP_EVENT_RENEWAL_COMPLETE 2
|
||||
#define UPNP_EVENT_UNSUBSCRIBE_COMPLETE 3
|
||||
|
||||
typedef struct _IPCon {
|
||||
char *ifname;
|
||||
} _IPCon;
|
||||
|
||||
typedef struct _IPCon *IPCon;
|
||||
|
||||
/*
|
||||
States :
|
||||
0 - Waiting for data to read
|
||||
1 - Waiting for HTTP Post Content.
|
||||
...
|
||||
>= 100 - to be deleted
|
||||
*/
|
||||
enum httpCommands {
|
||||
EUnknown = 0,
|
||||
EGet,
|
||||
EPost
|
||||
};
|
||||
|
||||
struct Upnp_Document_element {
|
||||
char *VarName;
|
||||
char *message;
|
||||
LIST_ENTRY(Upnp_Document_element) entries;
|
||||
};
|
||||
|
||||
typedef struct Upnp_Document_record {
|
||||
unsigned int TotalMessageLen; // (total strlen(VarName) * 2) + total strlen(message)
|
||||
unsigned short NumOfVarName;
|
||||
LIST_HEAD(DocumentHead, Upnp_Document_element) doc_head;
|
||||
} Upnp_Document_CTX, *Upnp_Document;
|
||||
|
||||
struct EvtRespElement {
|
||||
int socket;
|
||||
char sid[SID_LEN];
|
||||
unsigned short TimeOut;
|
||||
LIST_ENTRY(EvtRespElement) entries;
|
||||
};
|
||||
|
||||
struct process_upnp_subscription {
|
||||
char IP[IP_ADDRLEN];
|
||||
int IP_inet_addr;
|
||||
unsigned int port;
|
||||
char sid[SID_LEN];
|
||||
char callback_url[URL_MAX_LEN];
|
||||
unsigned long TimeOut;
|
||||
};
|
||||
|
||||
struct upnp_subscription_element {
|
||||
char IP[IP_ADDRLEN];
|
||||
int IP_inet_addr;
|
||||
unsigned int port;
|
||||
char sid[SID_LEN];
|
||||
char callback_url[URL_MAX_LEN];
|
||||
unsigned long seq;
|
||||
unsigned long TimeOut;
|
||||
unsigned int subscription_timeout;
|
||||
int eventID;
|
||||
int wscdReNewState; //add for wscd report renew state;2009-09-10
|
||||
LIST_ENTRY(upnp_subscription_element) entries;
|
||||
};
|
||||
|
||||
struct upnp_subscription_record {
|
||||
char my_IP[IP_ADDRLEN];
|
||||
unsigned int my_port;
|
||||
unsigned short total_subscription;
|
||||
unsigned short max_subscription_num;
|
||||
char event_url[URL_MAX_LEN];
|
||||
unsigned short max_subscription_time;
|
||||
unsigned short subscription_timeout;
|
||||
void (*EventCallBack)(struct upnp_subscription_element *sub);
|
||||
LIST_HEAD(subscriptionlisthead, upnp_subscription_element) subscription_head;
|
||||
LIST_HEAD(EvtResplisthead, EvtRespElement) EvtResp_head;
|
||||
};
|
||||
|
||||
struct upnphttp {
|
||||
int socket;
|
||||
/* Data structure added by Sean --begin-- */
|
||||
char IP[IP_ADDRLEN];
|
||||
struct _soapMethods *soapMethods;
|
||||
struct _sendDesc *sendDesc;
|
||||
struct upnp_subscription_record *subscribe_list;
|
||||
/* Data structure added by Sean --end-- */
|
||||
struct in_addr clientaddr; /* client address */
|
||||
int state;
|
||||
char HttpVer[16];
|
||||
/* request */
|
||||
char * req_buf;
|
||||
int req_buflen;
|
||||
int req_contentlen;
|
||||
int req_contentoff; /* header length */
|
||||
enum httpCommands req_command;
|
||||
char * req_soapAction;
|
||||
int req_soapActionLen;
|
||||
/* response */
|
||||
char * res_buf;
|
||||
int res_buflen;
|
||||
int res_buf_alloclen;
|
||||
/*int res_contentlen;*/
|
||||
/*int res_contentoff;*/ /* header length */
|
||||
LIST_ENTRY(upnphttp) entries;
|
||||
};
|
||||
|
||||
struct _soapMethods {
|
||||
char * methodName;
|
||||
void (*methodImpl)(struct upnphttp *h);
|
||||
};
|
||||
|
||||
struct _sendDesc {
|
||||
char * DescName;
|
||||
char * (*sendDescImpl)(int *len);
|
||||
};
|
||||
|
||||
struct upnphttp * New_upnphttp(int);
|
||||
|
||||
void CloseSocket_upnphttp(struct upnphttp *);
|
||||
|
||||
void Delete_upnphttp(struct upnphttp *);
|
||||
|
||||
void Process_upnphttp(struct upnphttp *);
|
||||
|
||||
/* Build the header for the HTTP Response
|
||||
* Also allocate the buffer for body data */
|
||||
void
|
||||
BuildHeader_upnphttp(struct upnphttp * h, int respcode,
|
||||
const char * respmsg,
|
||||
int bodylen);
|
||||
/* BuildResp_upnphttp() fill the res_buf buffer with the complete
|
||||
* HTTP 200 OK response from the body passed as argument */
|
||||
void BuildResp_upnphttp(struct upnphttp *, const char *, int);
|
||||
|
||||
/* same but with given response code/message */
|
||||
void
|
||||
BuildResp2_upnphttp(struct upnphttp * h, int respcode,
|
||||
const char * respmsg,
|
||||
const char * body, int bodylen);
|
||||
|
||||
void SendResp_upnphttp(struct upnphttp *);
|
||||
|
||||
extern Upnp_Document CreatePropertySet(void);
|
||||
extern int UpnpAddToPropertySet(Upnp_Document PropSet,
|
||||
const char *VarName, const char *message);
|
||||
extern void UpnpSendEventSingle(Upnp_Document PropSet,
|
||||
struct upnp_subscription_record *subscribe_list,
|
||||
struct upnp_subscription_element *sub);
|
||||
extern void UpnpSendEventAll(Upnp_Document PropSet,
|
||||
struct upnp_subscription_record *sub);
|
||||
extern void UpnpDocument_free(Upnp_Document PropSet);
|
||||
extern void ProcessEventingResp(struct EvtRespElement *EvtResp);
|
||||
extern int OpenAndConfHTTPSocket(const char * addr, unsigned short port);
|
||||
extern IPCon IPCon_New(char *ifname);
|
||||
extern IPCon IPCon_Destroy(IPCon this);
|
||||
extern BOOLEAN IPCon_GetIpAddr(IPCon this, struct in_addr *adr);
|
||||
extern char *IPCon_GetIpAddrByStr(IPCon this);
|
||||
extern int ILibBase64Encode(unsigned char* input, const int inputlen, unsigned char** output);
|
||||
extern int ILibBase64Decode(unsigned char* input, const int inputlen, unsigned char** output);
|
||||
extern int ReliableSend(int socket, const char *data, const int len);
|
||||
|
||||
// support HNAP1
|
||||
extern void SendError(struct upnphttp * h, const int code, const char *title, const char *realm, const char *body);
|
||||
extern int OpenAndConfUNIXSocket(const char *file_path);
|
||||
extern int CreateUnixSocket(const char *function_name,
|
||||
const char *file_path,
|
||||
const int time_out);
|
||||
extern int UnixSocketSendAndReceive(const char *function_name,
|
||||
const char *file_path,
|
||||
const int time_out,
|
||||
const char *in, char *out, const int out_len);
|
||||
#endif
|
||||
|
||||
|
397
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpreplyparse.c
Executable file
397
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpreplyparse.c
Executable file
@ -0,0 +1,397 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "upnpreplyparse.h"
|
||||
#include "minixml.h"
|
||||
|
||||
static void
|
||||
NameValueParserStartElt(void * d, const char * name, int l)
|
||||
{
|
||||
struct NameValueParserData * data = (struct NameValueParserData *)d;
|
||||
if(l>63)
|
||||
l = 63;
|
||||
memcpy(data->curelt, name, l);
|
||||
data->curelt[l] = '\0';
|
||||
}
|
||||
|
||||
static void
|
||||
NameValueParserGetData(void * d, const char * datas, int l)
|
||||
{
|
||||
struct NameValueParserData * data = (struct NameValueParserData *)d;
|
||||
struct NameValue * nv;
|
||||
|
||||
nv = malloc(sizeof(struct NameValue));
|
||||
memset(nv, 0, sizeof(struct NameValue));
|
||||
nv->value = (char *) malloc(l+1);
|
||||
memset(nv->value, 0, l+1);
|
||||
|
||||
strncpy(nv->name, data->curelt, 64);
|
||||
memcpy(nv->value, datas, l);
|
||||
LIST_INSERT_HEAD( &(data->head), nv, entries);
|
||||
}
|
||||
|
||||
void ParseNameValue(const char * buffer, int bufsize,
|
||||
struct NameValueParserData * data)
|
||||
{
|
||||
struct xmlparser parser;
|
||||
LIST_INIT(&(data->head));
|
||||
/* init xmlparser object */
|
||||
parser.xmlstart = buffer;
|
||||
parser.xmlsize = bufsize;
|
||||
parser.data = data;
|
||||
parser.starteltfunc = NameValueParserStartElt;
|
||||
parser.endeltfunc = 0;
|
||||
parser.datafunc = NameValueParserGetData;
|
||||
parser.attfunc = 0;
|
||||
parsexml(&parser);
|
||||
}
|
||||
|
||||
void ClearNameValueList(struct NameValueParserData * pdata)
|
||||
{
|
||||
struct NameValue * nv;
|
||||
|
||||
while((nv = pdata->head.lh_first) != NULL)
|
||||
{
|
||||
if (nv->value)
|
||||
free(nv->value);
|
||||
LIST_REMOVE(nv, entries);
|
||||
free(nv);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
GetValueFromNameValueList(struct NameValueParserData * pdata,
|
||||
const char * Name)
|
||||
{
|
||||
struct NameValue * nv;
|
||||
char * p = NULL;
|
||||
for(nv = pdata->head.lh_first;
|
||||
(nv != NULL) && (p == NULL);
|
||||
nv = nv->entries.le_next)
|
||||
{
|
||||
if(strcmp(nv->name, Name) == 0)
|
||||
p = nv->value;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
|
||||
const char * Name)
|
||||
{
|
||||
struct NameValue * nv;
|
||||
char * p = NULL;
|
||||
char * pname;
|
||||
for(nv = pdata->head.lh_first;
|
||||
(nv != NULL) && (p == NULL);
|
||||
nv = nv->entries.le_next)
|
||||
{
|
||||
pname = strrchr(nv->name, ':');
|
||||
if(pname)
|
||||
pname++;
|
||||
else
|
||||
pname = nv->name;
|
||||
if(strcmp(pname, Name)==0)
|
||||
p = nv->value;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* debug all-in-one function
|
||||
* do parsing then display to stdout */
|
||||
void DisplayNameValueList(char * buffer, int bufsize)
|
||||
{
|
||||
struct NameValueParserData pdata;
|
||||
struct NameValue * nv;
|
||||
ParseNameValue(buffer, bufsize, &pdata);
|
||||
for(nv = pdata.head.lh_first;
|
||||
nv != NULL;
|
||||
nv = nv->entries.le_next)
|
||||
{
|
||||
printf("%s = %s\n", nv->name, nv->value);
|
||||
}
|
||||
ClearNameValueList(&pdata);
|
||||
}
|
||||
|
||||
/* MUST free the returned buffer after this call */
|
||||
char *mini_UPnPGetFirstElement(char *file_start, unsigned int len, char *tag_name, unsigned int tag_name_len)
|
||||
{
|
||||
char * line;
|
||||
unsigned long file_end;
|
||||
unsigned long string_begin=0;
|
||||
unsigned long string_end=0;
|
||||
char *tag_name_first=NULL;
|
||||
char *tag_name_second=NULL;
|
||||
char *buf=NULL;
|
||||
unsigned int string_len=0;
|
||||
|
||||
if (file_start == NULL || tag_name == NULL)
|
||||
return NULL;
|
||||
|
||||
if (len <= 0 || tag_name_len <= 0)
|
||||
return NULL;
|
||||
|
||||
tag_name_first = (char *)malloc(tag_name_len+3);
|
||||
if (tag_name_first == NULL)
|
||||
return NULL;
|
||||
memcpy(tag_name_first+1, tag_name, tag_name_len);
|
||||
tag_name_first[0] = '<';
|
||||
tag_name_first[tag_name_len+1] = '>';
|
||||
tag_name_first[tag_name_len+2] = 0;
|
||||
|
||||
tag_name_second = (char *)malloc(tag_name_len+4);
|
||||
if (tag_name_second == NULL) {
|
||||
free(tag_name_first);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(tag_name_second+2, tag_name, tag_name_len);
|
||||
tag_name_second[0] = '<';
|
||||
tag_name_second[1] = '/';
|
||||
tag_name_second[tag_name_len+2] = '>';
|
||||
tag_name_second[tag_name_len+3] = 0;
|
||||
|
||||
line = file_start;
|
||||
file_end = (unsigned long)file_start + len;
|
||||
while ((unsigned long)line < (file_end-tag_name_len-3))
|
||||
{
|
||||
if (strncasecmp(line, tag_name_first, tag_name_len+2) == 0) {
|
||||
if (string_begin == 0) {
|
||||
string_begin = (unsigned long)line + tag_name_len + 2;
|
||||
}
|
||||
else {
|
||||
//DEBUG_ERR("Duplicated tag %s\n", tag_name_first);
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (strncasecmp(line, tag_name_second, tag_name_len+3) == 0) {
|
||||
if (string_begin == 0) {
|
||||
//DEBUG_ERR("Missing tag %s\n", tag_name_first);
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
string_end = (unsigned long)line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line++;
|
||||
}
|
||||
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
if (string_begin < string_end) {
|
||||
string_len = string_end - string_begin;
|
||||
buf = (char *)malloc(string_len+1);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
memcpy(buf, (char *)string_begin, string_len);
|
||||
buf[string_len] = 0;
|
||||
return buf;
|
||||
}
|
||||
else {
|
||||
//DEBUG_ERR("XML parse erroe!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *mini_UPnPGetFirstElementAndReturnAddr(char *file_start, unsigned int len, char *tag_name, unsigned int tag_name_len, char *buf)
|
||||
{
|
||||
char * line;
|
||||
unsigned long file_end;
|
||||
unsigned long string_begin=0;
|
||||
unsigned long string_end=0;
|
||||
char *tag_name_first=NULL;
|
||||
char *tag_name_second=NULL;
|
||||
unsigned int string_len=0;
|
||||
char *end=NULL;
|
||||
unsigned char found=0;
|
||||
|
||||
if (file_start == NULL || tag_name == NULL || buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (len <= 0 || tag_name_len <= 0)
|
||||
return NULL;
|
||||
|
||||
tag_name_first = (char *)malloc(tag_name_len+3);
|
||||
if (tag_name_first == NULL)
|
||||
return NULL;
|
||||
memcpy(tag_name_first+1, tag_name, tag_name_len);
|
||||
tag_name_first[0] = '<';
|
||||
tag_name_first[tag_name_len+1] = '>';
|
||||
tag_name_first[tag_name_len+2] = 0;
|
||||
|
||||
tag_name_second = (char *)malloc(tag_name_len+4);
|
||||
if (tag_name_second == NULL) {
|
||||
free(tag_name_first);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(tag_name_second+2, tag_name, tag_name_len);
|
||||
tag_name_second[0] = '<';
|
||||
tag_name_second[1] = '/';
|
||||
tag_name_second[tag_name_len+2] = '>';
|
||||
tag_name_second[tag_name_len+3] = 0;
|
||||
|
||||
line = file_start;
|
||||
file_end = (unsigned long)file_start + len;
|
||||
while ((unsigned long)line < (file_end-tag_name_len-3))
|
||||
{
|
||||
if (strncasecmp(line, tag_name_first, tag_name_len+2) == 0) {
|
||||
if (string_begin == 0) {
|
||||
string_begin = (unsigned long)line + tag_name_len + 2;
|
||||
}
|
||||
else {
|
||||
//DEBUG_ERR("Duplicated tag %s\n", tag_name_first);
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (strncasecmp(line, tag_name_second, tag_name_len+3) == 0) {
|
||||
if (string_begin == 0) {
|
||||
//DEBUG_ERR("Missing tag %s\n", tag_name_first);
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
string_end = (unsigned long)line;
|
||||
end = (char *)(line + (tag_name_len+3));
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line++;
|
||||
}
|
||||
|
||||
free(tag_name_first);
|
||||
free(tag_name_second);
|
||||
if (string_begin < string_end) {
|
||||
string_len = string_end - string_begin;
|
||||
memcpy(buf, (char *)string_begin, string_len);
|
||||
buf[string_len] = 0;
|
||||
return end;
|
||||
}
|
||||
else {
|
||||
if (found) {
|
||||
buf[0] = 0;
|
||||
return end;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *mini_UPnP_UploadXML(char *file_path)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int retVal = 0;
|
||||
struct stat file_info;
|
||||
char *buf=NULL;
|
||||
unsigned int fileLen=0;
|
||||
unsigned int num_read=0;
|
||||
char *membuf=NULL;
|
||||
|
||||
buf = file_path;
|
||||
retVal = stat(buf, &file_info );
|
||||
if ( retVal == -1 ) {
|
||||
//printf("Failed to get file info. EXITING\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fileLen = file_info.st_size;
|
||||
if ( ( fp = fopen( buf, "rb" ) ) == NULL ) {
|
||||
printf("Failed to open file [%s]. EXITING\n", buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ( membuf = ( char * )malloc( fileLen + 1 ) ) == NULL ) {
|
||||
fclose( fp );
|
||||
printf("mini_UPnP_UploadXML Out of memory! EXITING\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num_read = fread( membuf, 1, fileLen, fp );
|
||||
if ( num_read != fileLen ) {
|
||||
fclose( fp );
|
||||
free( membuf );
|
||||
printf("mini_UPnP_UploadXML File length mismatched! EXITING\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
membuf[fileLen] = 0;
|
||||
fclose( fp );
|
||||
|
||||
return membuf;
|
||||
}
|
||||
|
||||
char *get_token(char *data, char *token)
|
||||
{
|
||||
char *ptr=data;
|
||||
int len=0, idx=0;
|
||||
|
||||
while (*ptr && *ptr != '\n' ) {
|
||||
if (*ptr == '=') {
|
||||
if (len <= 1)
|
||||
return NULL;
|
||||
memcpy(token, data, len);
|
||||
|
||||
/* delete ending space */
|
||||
for (idx=len-1; idx>=0; idx--) {
|
||||
if (token[idx] != ' ')
|
||||
break;
|
||||
}
|
||||
token[idx+1] = '\0';
|
||||
|
||||
return ptr+1;
|
||||
}
|
||||
len++;
|
||||
ptr++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_value(char *data, char *value)
|
||||
{
|
||||
char *ptr=data;
|
||||
int len=0, idx, i;
|
||||
|
||||
while (*ptr && *ptr != '\n' && *ptr != '\r') {
|
||||
len++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* delete leading space */
|
||||
idx = 0;
|
||||
while (len-idx > 0) {
|
||||
if (data[idx] != ' ')
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
len -= idx;
|
||||
|
||||
/* delete bracing '"' */
|
||||
if (data[idx] == '"') {
|
||||
for (i=idx+len-1; i>idx; i--) {
|
||||
if (data[i] == '"') {
|
||||
idx++;
|
||||
len = i - idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
memcpy(value, &data[idx], len);
|
||||
value[len] = '\0';
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
69
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpreplyparse.h
Executable file
69
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpreplyparse.h
Executable file
@ -0,0 +1,69 @@
|
||||
/* $Id: upnpreplyparse.h,v 1.1.1.1 2007/08/06 10:04:43 root Exp $ */
|
||||
/* miniupnp project
|
||||
* see http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
|
||||
* (c) 2005-2006 Thomas Bernard
|
||||
* This software is subjects to the conditions detailed in the LICENCE
|
||||
* file provided with this distribution */
|
||||
#ifndef __UPNPREPLYPARSE_H__
|
||||
#define __UPNPREPLYPARSE_H__
|
||||
|
||||
#if defined(sun) || defined(__sun) || defined(WIN32)
|
||||
#include "bsdqueue.h"
|
||||
#else
|
||||
#include <sys/queue.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct NameValue {
|
||||
LIST_ENTRY(NameValue) entries;
|
||||
char name[64];
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct NameValueParserData {
|
||||
LIST_HEAD(listhead, NameValue) head;
|
||||
char curelt[64];
|
||||
};
|
||||
|
||||
void
|
||||
ParseNameValue(const char * buffer, int bufsize,
|
||||
struct NameValueParserData * data);
|
||||
|
||||
void
|
||||
ClearNameValueList(struct NameValueParserData * pdata);
|
||||
|
||||
char *
|
||||
GetValueFromNameValueList(struct NameValueParserData * pdata,
|
||||
const char * Name);
|
||||
|
||||
char *
|
||||
GetValueFromNameValueListIgnoreNS(struct NameValueParserData * pdata,
|
||||
const char * Name);
|
||||
|
||||
void
|
||||
DisplayNameValueList(char * buffer, int bufsize);
|
||||
|
||||
char *
|
||||
mini_UPnPGetFirstElement(char *file_start, unsigned int len,
|
||||
char *tag_name, unsigned int tag_name_len);
|
||||
|
||||
char *
|
||||
mini_UPnPGetFirstElementAndReturnAddr(char *file_start, unsigned int len, char *tag_name, unsigned int tag_name_len, char *buf);
|
||||
|
||||
char *
|
||||
mini_UPnP_UploadXML(char *file_path);
|
||||
|
||||
char *
|
||||
get_token(char *data, char *token);
|
||||
|
||||
int
|
||||
get_value(char *data, char *value);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
124
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpsoap.c
Executable file
124
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpsoap.c
Executable file
@ -0,0 +1,124 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "upnphttp.h"
|
||||
#include "upnpsoap.h"
|
||||
|
||||
void
|
||||
BuildSendAndCloseSoapResp(struct upnphttp * h,
|
||||
const char * body, int bodylen)
|
||||
{
|
||||
static const char beforebody[] =
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body>";
|
||||
static const char afterbody[] =
|
||||
"</s:Body>"
|
||||
"</s:Envelope>";
|
||||
|
||||
BuildHeader_upnphttp(h, 200, "OK", sizeof(beforebody) - 1
|
||||
+ sizeof(afterbody) - 1
|
||||
+ bodylen );
|
||||
memcpy(h->res_buf + h->res_buflen, beforebody, sizeof(beforebody) - 1);
|
||||
h->res_buflen += sizeof(beforebody) - 1;
|
||||
memcpy(h->res_buf + h->res_buflen, body, bodylen);
|
||||
h->res_buflen += bodylen;
|
||||
memcpy(h->res_buf + h->res_buflen, afterbody, sizeof(afterbody) - 1);
|
||||
h->res_buflen += sizeof(afterbody) - 1;
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
}
|
||||
|
||||
void ExecuteSoapAction(struct upnphttp * h, const char * action, int n)
|
||||
{
|
||||
char * p;
|
||||
int i, len;
|
||||
i = 0;
|
||||
|
||||
// support HNAP1
|
||||
len = strlen("http://purenetworks.com/HNAP");
|
||||
if (strncasecmp((char *)action, "http://purenetworks.com/HNAP", len) == 0) {
|
||||
char *pos;
|
||||
pos = (char *)(action + len);
|
||||
p = strchr(pos, '/');
|
||||
//if (p)
|
||||
//printf("action [%s]\n", p+1);
|
||||
}
|
||||
else
|
||||
p = strchr(action, '#');
|
||||
if (p)
|
||||
{
|
||||
p++;
|
||||
while(h->soapMethods[i].methodName)
|
||||
{
|
||||
len = strlen(h->soapMethods[i].methodName);
|
||||
if(strncmp(p, h->soapMethods[i].methodName, len) == 0)
|
||||
{
|
||||
h->soapMethods[i].methodImpl(h);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
syslog(LOG_NOTICE, "Unknown soap method");
|
||||
SoapError(h, 401, "Invalid Action");
|
||||
}
|
||||
|
||||
/* Standard errors :
|
||||
errorCode errorDescription Description
|
||||
401 Invalid Action No action by that name at this service.
|
||||
402 Invalid Args Could be any of the following: not enough in args, too many in args, no in arg by that name, one or more in args are of the wrong data type.
|
||||
403 Out of Sync Out of synchronization.
|
||||
501 Action Failed May be returned in current state of service prevents invoking that action.
|
||||
600-699 TBD Common action errors. Defined by UPnP Forum Technical Committee.
|
||||
700-799 TBD Action-specific errors for standard actions. Defined by UPnP Forum working committee.
|
||||
800-899 TBD Action-specific errors for non-standard actions. Defined by UPnP vendor.
|
||||
*/
|
||||
void
|
||||
SoapError(struct upnphttp * h, int errCode, const char * errDesc)
|
||||
{
|
||||
char *body=NULL;
|
||||
int bodylen;
|
||||
static const char resp[] =
|
||||
"<s:Envelope "
|
||||
"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body>"
|
||||
"<s:Fault>"
|
||||
"<faultcode>s:Client</faultcode>"
|
||||
"<faultstring>UPnPError</faultstring>"
|
||||
"<detail>"
|
||||
"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">"
|
||||
"<errorCode>%d</errorCode>"
|
||||
"<errorDescription>%s</errorDescription>"
|
||||
"</UPnPError>"
|
||||
"</detail>"
|
||||
"</s:Fault>"
|
||||
"</s:Body>"
|
||||
"</s:Envelope>";
|
||||
|
||||
body = (char *) malloc(2048);
|
||||
if (body == NULL) {
|
||||
syslog(LOG_ERR, "SoapError: out of memory!");
|
||||
return;
|
||||
}
|
||||
memset(body, 0, 2048);
|
||||
|
||||
bodylen = sprintf(body, resp, errCode, errDesc);
|
||||
BuildResp2_upnphttp(h, 500, "Internal Server Error", body, bodylen);
|
||||
SendResp_upnphttp(h);
|
||||
CloseSocket_upnphttp(h);
|
||||
free(body);
|
||||
}
|
||||
|
||||
|
15
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpsoap.h
Executable file
15
wlan/8192es/DriverSrcPkg/Users/mini_upnp/upnpsoap.h
Executable file
@ -0,0 +1,15 @@
|
||||
#ifndef _UPNPSOAP_H_
|
||||
#define _UPNPSOAP_H_
|
||||
|
||||
/* ExecuteSoapAction() :
|
||||
* This method execute the requested Soap Action */
|
||||
void ExecuteSoapAction(struct upnphttp *, const char *, int);
|
||||
|
||||
/* Sends a correct SOAP error with an UPNPError code and
|
||||
* description */
|
||||
void
|
||||
SoapError(struct upnphttp * h, int errCode, const char * errDesc);
|
||||
|
||||
extern void BuildSendAndCloseSoapResp(struct upnphttp * h, const char * body, int bodylen);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user