Ejemplo n.º 1
0
/* simpleUPnPcommand2 :
 * not so simple !
 * return values :
 *   pointer - OK
 *   NULL - error */
static char *
simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
                   const char * action, struct UPNParg * args,
                   int * bufsize, const char * httpversion)
{
	char hostname[MAXHOSTNAMELEN+1];
	unsigned short port = 0;
	char * path;
	char soapact[128];
	char soapbody[2048];
	int soapbodylen;
	char * buf;
	int n;
	int status_code;

	*bufsize = 0;
	snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
	if(args==NULL)
	{
		soapbodylen = snprintf(soapbody, sizeof(soapbody),
						  "<?xml version=\"1.0\"?>\r\n"
						  "<" SOAPPREFIX ":Envelope "
						  "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
						  SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
						  "<" SOAPPREFIX ":Body>"
						  "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
						  "</" SERVICEPREFIX ":%s>"
						  "</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
						  "\r\n", action, service, action);
		if ((unsigned int)soapbodylen >= sizeof(soapbody))
			return NULL;
	}
	else
	{
		char * p;
		const char * pe, * pv;
		const char * const pend = soapbody + sizeof(soapbody);
		soapbodylen = snprintf(soapbody, sizeof(soapbody),
						"<?xml version=\"1.0\"?>\r\n"
						"<" SOAPPREFIX ":Envelope "
						"xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
						SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
						"<" SOAPPREFIX ":Body>"
						"<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
						action, service);
		if ((unsigned int)soapbodylen >= sizeof(soapbody))
			return NULL;
		p = soapbody + soapbodylen;
		while(args->elt)
		{
			if(p >= pend) /* check for space to write next byte */
				return NULL;
			*(p++) = '<';

			pe = args->elt;
			while(p < pend && *pe)
				*(p++) = *(pe++);

			if(p >= pend) /* check for space to write next byte */
				return NULL;
			*(p++) = '>';

			if((pv = args->val))
			{
				while(p < pend && *pv)
					*(p++) = *(pv++);
			}

			if((p+2) > pend) /* check for space to write next 2 bytes */
				return NULL;
			*(p++) = '<';
			*(p++) = '/';

			pe = args->elt;
			while(p < pend && *pe)
				*(p++) = *(pe++);

			if(p >= pend) /* check for space to write next byte */
				return NULL;
			*(p++) = '>';

			args++;
		}
		if((p+4) > pend) /* check for space to write next 4 bytes */
			return NULL;
		*(p++) = '<';
		*(p++) = '/';
		*(p++) = SERVICEPREFIX2;
		*(p++) = ':';

		pe = action;
		while(p < pend && *pe)
			*(p++) = *(pe++);

		strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
		        pend - p);
		if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */
			return NULL;
	}
	if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
	if(ISINVALID(s)) {
		s = connecthostport(hostname, port, 0);
		if(ISINVALID(s)) {
			/* failed to connect */
			return NULL;
		}
	}

	n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
	if(n<=0) {
#ifdef DEBUG
		printf("Error sending SOAP request\n");
#endif
		closesocket(s);
		return NULL;
	}

	buf = getHTTPResponse(s, bufsize, &status_code);
#ifdef DEBUG
	if(*bufsize > 0 && buf)
	{
		printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf);
	}
	else
	{
		printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize);
	}
#endif
	closesocket(s);
	return buf;
}
Ejemplo n.º 2
0
void am_log_register_instance(unsigned long instance_id, const char *debug_log, int log_level, int log_size,
        const char *audit_log, int audit_level, int audit_size) {
    int i, exist = AM_NOT_FOUND;
    struct am_log *log = AM_LOG();
    struct log_files *f = NULL;

    if (log == NULL || instance_id == 0 || ISINVALID(debug_log) || ISINVALID(audit_log)) {
        return;
    }

#ifdef _WIN32
    WaitForSingleObject(am_log_lck.lock, INFINITE);
#else
    pthread_mutex_lock(&log->lock);
#endif
    for (i = 0; i < AM_MAX_INSTANCES; i++) {
        f = &log->files[i];
        if (f->instance_id == instance_id) {
            exist = AM_SUCCESS;
            break;
        }
    }
    if (exist == AM_NOT_FOUND) {
        for (i = 0; i < AM_MAX_INSTANCES; i++) {
            f = &log->files[i];
            if (!f->used) {
                f->instance_id = instance_id;
                snprintf(f->name_debug, sizeof (f->name_debug), "%s", debug_log);
                snprintf(f->name_audit, sizeof (f->name_audit), "%s", audit_log);
                f->used = AM_TRUE;

#define DEFAULT_LOG_SIZE (1024 * 1024 * 5) /* 5MB */

                f->max_size_debug = log_size > 0 && log_size < DEFAULT_LOG_SIZE ? DEFAULT_LOG_SIZE : log_size;
                f->max_size_audit = audit_size > 0 && audit_size < DEFAULT_LOG_SIZE ? DEFAULT_LOG_SIZE : audit_size;
                f->level_debug = log_level;
                f->level_audit = audit_level;
                f->created_debug = f->created_audit = 0;
                f->owner = 0;
                exist = AM_DONE;
                break;
            }
        }
    } else {
        /* update instance logging level configuration */
        f->max_size_debug = log_size > 0 && log_size < DEFAULT_LOG_SIZE ? DEFAULT_LOG_SIZE : log_size;
        f->max_size_audit = audit_size > 0 && audit_size < DEFAULT_LOG_SIZE ? DEFAULT_LOG_SIZE : audit_size;
        f->level_debug = log_level;
        f->level_audit = audit_level;
    }
#ifdef _WIN32
    ReleaseMutex(am_log_lck.lock);
#else
    pthread_mutex_unlock(&log->lock);
#endif
    if (exist == AM_DONE) {
#define AM_LOG_HEADER "\r\n\r\n\t######################################################\r\n\t# %-51s#\r\n\t# Version: %-42s#\r\n\t# %-51s#\r\n\t# Build date: %s %-27s#\r\n\t######################################################\r\n"

        AM_LOG_ALWAYS(instance_id, AM_LOG_HEADER, DESCRIPTION, VERSION,
                VERSION_VCS, __DATE__, __TIME__);

        am_agent_init_set_value(instance_id, AM_TRUE, AM_UNKNOWN);
    }
}
Ejemplo n.º 3
0
static void *am_log_worker(void *arg) {
    struct am_log *log = AM_LOG();
    int i, level, is_audit;
    unsigned int index;
    char *data;
    size_t data_sz;
    unsigned long instance_id;
    struct stat st;
    struct log_files *f;

    if (log == NULL) {
        return NULL;
    }

#ifdef _WIN32
    WaitForSingleObject(am_log_lck.lock, INFINITE);
#else
    pthread_mutex_lock(&log->lock);
#endif

    for (;;) {
        index = log->out;

#ifdef _WIN32
        while (log->read_count == 0 || !log->bucket[index].ready_to_read) {
            ReleaseMutex(am_log_lck.lock);
            if (WaitForSingleObject(am_log_lck.new_data_cond, 1000) == WAIT_TIMEOUT) {
                if (WaitForSingleObject(am_log_lck.exit, 0) == WAIT_OBJECT_0) {
                    return NULL;
                }
            }
            WaitForSingleObject(am_log_lck.lock, INFINITE);
        }
#else
        while (log->read_count == 0 || !log->bucket[index].ready_to_read) {
            struct timeval now = {0, 0};
            struct timespec ts = {0, 0};
            gettimeofday(&now, NULL);
            ts.tv_sec = now.tv_sec + 1;
            ts.tv_nsec = now.tv_usec * 1000;
            if (pthread_cond_timedwait(&log->new_data_cond, &log->lock, &ts) == ETIMEDOUT) {
                if (should_exit(&log->exit)) {
                    pthread_mutex_unlock(&log->lock);
                    return NULL;
                }
            }
        }
#endif  /* _WIN32 */

        log->bucket[index].ready_to_read = AM_FALSE;
#ifdef _WIN32
        ReleaseMutex(am_log_lck.lock);
#else
        pthread_mutex_unlock(&log->lock);
#endif  /* _WIN32 */

        data = log->bucket[index].data;
        data_sz = log->bucket[index].size;
        level = log->bucket[index].level;
        is_audit = (level & AM_LOG_LEVEL_AUDIT) != 0;
        instance_id = log->bucket[index].instance_id;

        f = NULL;

        for (i = 0; i < AM_MAX_INSTANCES; i++) {
            f = &log->files[i];
            if (f->used && f->instance_id == instance_id) {
                break;
            }
        }

        if (f != NULL) {
            
            if (ISINVALID(f->name_debug)) {
                fprintf(stderr, "am_log_worker(): the debug file name is invalid (i.e. empty or null)\n");
                f->fd_debug = -1;
                f->fd_audit = -1;
                return NULL;
            }
            
            if (ISINVALID(f->name_audit)) {
                fprintf(stderr, "am_log_worker(): the audit file name is invalid (i.e. empty or null)\n");
                f->fd_debug = -1;
                f->fd_audit = -1;
                return NULL;
            }
            
            /* log files are not opened yet, do it now */
            if (f->fd_audit == -1 && f->fd_debug == -1) {
#ifdef _WIN32
                f->fd_debug = _open(f->name_debug, _O_CREAT | _O_WRONLY | _O_APPEND | _O_BINARY,
                        _S_IREAD | _S_IWRITE);
                f->fd_audit = _open(f->name_audit, _O_CREAT | _O_WRONLY | _O_APPEND | _O_BINARY,
                        _S_IREAD | _S_IWRITE);
                if (f->fd_debug != -1 && stat(f->name_debug, &st) == 0) {
                    f->created_debug = st.st_ctime;
                    f->owner = getpid();
                }
                if (f->fd_audit != -1 && stat(f->name_audit, &st) == 0) {
                    f->created_audit = st.st_ctime;
                    f->owner = getpid();
                }
#else
                f->fd_debug = open(f->name_debug, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR);
                f->fd_audit = open(f->name_audit, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR);
                if (f->fd_debug != -1 && stat(f->name_debug, &st) == 0) {
                    f->node_debug = st.st_ino;
                    f->created_debug = st.st_ctime;
                    f->owner = getpid();
                }
                if (f->fd_audit != -1 && stat(f->name_audit, &st) == 0) {
                    f->node_audit = st.st_ino;
                    f->created_audit = st.st_ctime;
                    f->owner = getpid();
                }
#endif
            }

            if (f->fd_debug == -1) {
                fprintf(stderr, "am_log_worker() failed to open log file %s: error: %d", f->name_debug, errno);
                f->fd_debug = f->fd_audit = -1;
            } else if (f->fd_audit == -1) {
                fprintf(stderr, "am_log_worker() failed to open audit file %s: error: %d", f->name_audit, errno);
                f->fd_debug = f->fd_audit = -1;
            } else {
                int file_handle = is_audit ? f->fd_audit : f->fd_debug;
                char *file_name = is_audit ? f->name_audit : f->name_debug;
                int max_size = is_audit ? f->max_size_audit : f->max_size_debug;
                time_t file_created = is_audit ? f->created_audit : f->created_debug;
#ifdef _WIN32
                int wrote;
#else 
                ssize_t wrote;
                ino_t file_inode = is_audit ? f->node_audit : f->node_debug;
#endif
                wrote = write(file_handle, data, (unsigned int) data_sz);
#ifdef _WIN32
                wrote = write(file_handle, "\r\n", 2);
                _commit(file_handle);

                /* check file timestamp; rotate by date if set so */
                if (max_size == -1 && should_rotate_time(file_created)) {
                    HANDLE fh = (HANDLE) _get_osfhandle(file_handle);
                    unsigned int idx = 1;
                    static char tmp[AM_PATH_SIZE];
                    do {
                        snprintf(tmp, sizeof (tmp), "%s.%d", file_name, idx);
                        idx++;
                    } while (_access(tmp, 0) == 0);
                    if (CopyFileA(file_name, tmp, FALSE)) {
                        SetFilePointer(fh, 0, NULL, FILE_BEGIN);
                        SetEndOfFile(fh);
                        if (is_audit) {
                            f->created_audit = time(NULL);
                        } else {
                            f->created_debug = time(NULL);
                        }
                    } else {
                        fprintf(stderr, "could not rotate log file %s (error: %d)\n",
                                file_name, GetLastError());
                    }
                }

                /* check file size; rotate by size if set so */
                if (max_size > 0) {
                    BY_HANDLE_FILE_INFORMATION info;
                    uint64_t fsz = 0;
                    HANDLE fh = (HANDLE) _get_osfhandle(file_handle);
                    if (GetFileInformationByHandle(fh, &info)) {
                        fsz = ((DWORDLONG) (((DWORD) (info.nFileSizeLow)) |
                                (((DWORDLONG) ((DWORD) (info.nFileSizeHigh))) << 32)));
                    }
                    if ((fsz + 1024) > max_size) {
                        unsigned int idx = 1;
                        static char tmp[AM_PATH_SIZE];
                        do {
                            snprintf(tmp, sizeof (tmp), "%s.%d", file_name, idx);
                            idx++;
                        } while (_access(tmp, 0) == 0);
                        if (CopyFileA(file_name, tmp, FALSE)) {
                            SetFilePointer(fh, 0, NULL, FILE_BEGIN);
                            SetEndOfFile(fh);
                            if (is_audit) {
                                f->created_audit = time(NULL);
                            } else {
                                f->created_debug = time(NULL);
                            }
                        } else {
                            fprintf(stderr, "could not rotate log file %s (error: %d)\n",
                                    file_name, GetLastError());
                        }
                    }
                }
#else
                wrote = write(file_handle, "\n", 1);
                fsync(file_handle);

                /* check file timestamp; rotate by date if set so */
                if (max_size == -1 && should_rotate_time(file_created)) {
                    rename_file(file_name);
                }

                /* check file size; rotate by size if set so */
                if (max_size > 0 && stat(file_name, &st) == 0 && (st.st_size + 1024) > max_size) {
                    rename_file(file_name);
                }

                /* reset file inode number (in case it has changed as a result of rename_file) */
                if (stat(file_name, &st) != 0 || st.st_ino != file_inode) {
                    close(file_handle);
                    if (is_audit) {
                        f->fd_audit = open(f->name_audit, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR);
                        f->node_audit = st.st_ino;
                        f->created_audit = st.st_ctime;
                        f->owner = getpid();
                    } else {
                        f->fd_debug = open(f->name_debug, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR);
                        f->node_debug = st.st_ino;
                        f->created_debug = st.st_ctime;
                        f->owner = getpid();
                    }
                    if (f->fd_debug == -1 || f->fd_audit == -1) {
                        fprintf(stderr, "am_log_worker() log file re-open failed with error: %d", errno);
                        f->fd_debug = f->fd_audit = -1;
                    }
                }
#endif                            
            }
        }

        log->out = AM_LOG_BUFFER_MASK(log->out + 1, log->bucket_count);
#ifdef _WIN32
        WaitForSingleObject(am_log_lck.lock, INFINITE);
#else
        pthread_mutex_lock(&log->lock);
#endif
        log->read_count--;
#ifdef _WIN32
        SetEvent(am_log_lck.new_space_cond);
#else
        pthread_cond_broadcast(&log->new_space_cond);
#endif
    }
    return NULL;
}
Ejemplo n.º 4
0
/* ssdpDiscoverDevices() :
 * return a chained list of all devices found or NULL if
 * no devices was found.
 * It is up to the caller to free the chained list
 * delay is in millisecond (poll).
 * UDA v1.1 says :
 *   The TTL for the IP packet SHOULD default to 2 and
 *   SHOULD be configurable. */
struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
                    int delay, const char * multicastif,
                    int localport,
                    int ipv6, unsigned char ttl,
                    int * error,
                    int searchalltypes)
{
	struct UPNPDev * tmp;
	struct UPNPDev * devlist = 0;
	unsigned int scope_id = 0;
	int opt = 1;
	static const char MSearchMsgFmt[] =
	"M-SEARCH * HTTP/1.1\r\n"
	"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
	"ST: %s\r\n"
	"MAN: \"ssdp:discover\"\r\n"
	"MX: %u\r\n"
	"\r\n";
	int deviceIndex;
	char bufr[1536];	/* reception and emission buffer */
	SOCKET sudp;
	int n;
	struct sockaddr_storage sockudp_r;
	unsigned int mx;
#ifdef NO_GETADDRINFO
	struct sockaddr_storage sockudp_w;
#else
	int rv;
	struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
	unsigned long _ttl = (unsigned long)ttl;
#endif
	int linklocal = 1;
	int sentok;

	if(error)
		*error = MINISSDPC_UNKNOWN_ERROR;

	if(localport==UPNP_LOCAL_PORT_SAME)
		localport = SSDP_PORT;

#ifdef _WIN32
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
	if(ISINVALID(sudp))
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("socket");
		return NULL;
	}
	/* reception */
	memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
	if(ipv6) {
		struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
		p->sin6_family = AF_INET6;
		if(localport > 0 && localport < 65536)
			p->sin6_port = htons((unsigned short)localport);
		p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
	} else {
		struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
		p->sin_family = AF_INET;
		if(localport > 0 && localport < 65536)
			p->sin_port = htons((unsigned short)localport);
		p->sin_addr.s_addr = INADDR_ANY;
	}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
 * SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
 * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
	if(!ipv6) {
		DWORD ifbestidx;
		SOCKADDR_IN destAddr;
		memset(&destAddr, 0, sizeof(destAddr));
		destAddr.sin_family = AF_INET;
		destAddr.sin_addr.s_addr = inet_addr("223.255.255.255");
		destAddr.sin_port = 0;
		if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) {
			DWORD dwRetVal = 0;
			PIP_ADAPTER_ADDRESSES pAddresses = NULL;
			ULONG outBufLen = 0;
			ULONG Iterations = 0;
			PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
			PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

			outBufLen = 15360;
			do {
				pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, outBufLen);
				if (pAddresses == NULL) {
					break;
				}

				dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &outBufLen);

				if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
					HeapFree(GetProcessHeap(), 0, pAddresses);
					pAddresses = NULL;
				} else {
					break;
				}
				Iterations++;
			} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < 3));

			if (dwRetVal == NO_ERROR) {
				pCurrAddresses = pAddresses;
				while (pCurrAddresses) {
#ifdef DEBUG
					int i;
					PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
					PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;

					printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex);
					printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);
					pUnicast = pCurrAddresses->FirstUnicastAddress;
					if (pUnicast != NULL) {
						for (i = 0; pUnicast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pUnicast->Address;
							printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
							pUnicast = pUnicast->Next;
						}
						printf("\tNumber of Unicast Addresses: %d\n", i);
					}
					pAnycast = pCurrAddresses->FirstAnycastAddress;
					if (pAnycast) {
						for (i = 0; pAnycast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pAnyCast->Address;
							printf("\tAnycast Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
							pAnycast = pAnycast->Next;
						}
						printf("\tNumber of Anycast Addresses: %d\n", i);
					}
					pMulticast = pCurrAddresses->FirstMulticastAddress;
					if (pMulticast) {
						for (i = 0; pMulticast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pMultiCast->Address;
							printf("\tMulticast Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
						}
					}
					printf("\n");
#endif
					pUnicast = pCurrAddresses->FirstUnicastAddress;
					if (pCurrAddresses->IfIndex == ifbestidx && pUnicast != NULL) {
						SOCKADDR_IN *ipv4 = (SOCKADDR_IN *)(pUnicast->Address.lpSockaddr);
						/* Set the address of this interface to be used */
						struct in_addr mc_if;
						memset(&mc_if, 0, sizeof(mc_if));
						mc_if.s_addr = ipv4->sin_addr.s_addr;
						if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
							PRINT_SOCKET_ERROR("setsockopt");
						}
						((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = ipv4->sin_addr.s_addr;
#ifndef DEBUG
						break;
#endif
					}
					pCurrAddresses = pCurrAddresses->Next;
				}
			}
			if (pAddresses != NULL) {
				HeapFree(GetProcessHeap(), 0, pAddresses);
				pAddresses = NULL;
			}
		}
	}
#endif	/* _WIN32 */

#ifdef _WIN32
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)");
		return NULL;
	}

	if(ipv6) {
#ifdef _WIN32
		DWORD mcastHops = ttl;
		if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0)
#else  /* _WIN32 */
		int mcastHops = ttl;
		if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0)
#endif /* _WIN32 */
		{
			PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)");
		}
	} else {
#ifdef _WIN32
		if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
#else  /* _WIN32 */
		if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
#endif /* _WIN32 */
		{
			/* not a fatal error */
			PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
		}
	}

	if(multicastif)
	{
		if(ipv6) {
#if !defined(_WIN32)
			/* according to MSDN, if_nametoindex() is supported since
			 * MS Windows Vista and MS Windows Server 2008.
			 * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
			unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
			if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
			{
				PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
			}
#else
#ifdef DEBUG
			printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
		} else {
			struct in_addr mc_if;
#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
			InetPtonA(AF_INET, multicastif, &mc_if);
#else
			mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
#endif
			if(mc_if.s_addr != INADDR_NONE)
			{
				((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
			} else {
#ifdef HAS_IP_MREQN
				/* was not an ip address, try with an interface name */
				struct ip_mreqn reqn;	/* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
				memset(&reqn, 0, sizeof(struct ip_mreqn));
				reqn.imr_ifindex = if_nametoindex(multicastif);
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
#elif !defined(_WIN32)
				struct ifreq ifr;
				int ifrlen = sizeof(ifr);
				strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
				ifr.ifr_name[IFNAMSIZ-1] = '\0';
				if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
				{
					PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
				}
				mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
#else /* _WIN32 */
#ifdef DEBUG
				printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */
			}
		}
	}

	/* Before sending the packed, we first "bind" in order to be able
	 * to receive the response */
	if (bind(sudp, (const struct sockaddr *)&sockudp_r,
	         ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("bind");
		closesocket(sudp);
		return NULL;
	}

	if(error)
		*error = MINISSDPC_SUCCESS;
	/* Calculating maximum response time in seconds */
	mx = ((unsigned int)delay) / 1000u;
	if(mx == 0) {
		mx = 1;
		delay = 1000;
	}
	/* receiving SSDP response packet */
	for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
		sentok = 0;
		/* sending the SSDP M-SEARCH packet */
		n = snprintf(bufr, sizeof(bufr),
		             MSearchMsgFmt,
		             ipv6 ?
		             (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		             : UPNP_MCAST_ADDR,
		             deviceTypes[deviceIndex], mx);
		if ((unsigned int)n >= sizeof(bufr)) {
			if(error)
				*error = MINISSDPC_MEMORY_ERROR;
			goto error;
		}
#ifdef DEBUG
		/*printf("Sending %s", bufr);*/
		printf("Sending M-SEARCH request to %s with ST: %s\n",
		       ipv6 ?
		       (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		       : UPNP_MCAST_ADDR,
		       deviceTypes[deviceIndex]);
#endif
#ifdef NO_GETADDRINFO
		/* the following code is not using getaddrinfo */
		/* emission */
		memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
		if(ipv6) {
			struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
			p->sin6_family = AF_INET6;
			p->sin6_port = htons(SSDP_PORT);
			inet_pton(AF_INET6,
			          linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
			          &(p->sin6_addr));
		} else {
			struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
			p->sin_family = AF_INET;
			p->sin_port = htons(SSDP_PORT);
			p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
		}
		n = sendto(sudp, bufr, n, 0, &sockudp_w,
		           ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
		if (n < 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
			PRINT_SOCKET_ERROR("sendto");
		} else {
			sentok = 1;
		}
#else /* #ifdef NO_GETADDRINFO */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
		hints.ai_socktype = SOCK_DGRAM;
		/*hints.ai_flags = */
		if ((rv = getaddrinfo(ipv6
		                      ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
		                      : UPNP_MCAST_ADDR,
		                      XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
#ifdef _WIN32
			fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
			fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
			break;
		}
		for(p = servinfo; p; p = p->ai_next) {
			n = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen);
			if (n < 0) {
#ifdef DEBUG
				char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
				if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
				                sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
					fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
				}
#endif
				PRINT_SOCKET_ERROR("sendto");
				continue;
			} else {
				sentok = 1;
			}
		}
		freeaddrinfo(servinfo);
		if(!sentok) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
		}
#endif /* #ifdef NO_GETADDRINFO */
		/* Waiting for SSDP REPLY packet to M-SEARCH
		 * if searchalltypes is set, enter the loop only
		 * when the last deviceType is reached */
		if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do {
			n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
			if (n < 0) {
				/* error */
				if(error)
					*error = MINISSDPC_SOCKET_ERROR;
				goto error;
			} else if (n == 0) {
				/* no data or Time Out */
#ifdef DEBUG
				printf("NODATA or TIMEOUT\n");
#endif /* DEBUG */
				if (devlist && !searchalltypes) {
					/* found some devices, stop now*/
					if(error)
						*error = MINISSDPC_SUCCESS;
					goto error;
				}
			} else {
				const char * descURL=NULL;
				int urlsize=0;
				const char * st=NULL;
				int stsize=0;
				const char * usn=NULL;
				int usnsize=0;
				parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
				if(st&&descURL) {
#ifdef DEBUG
					printf("M-SEARCH Reply:\n  ST: %.*s\n  USN: %.*s\n  Location: %.*s\n",
					       stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
#endif /* DEBUG */
					for(tmp=devlist; tmp; tmp = tmp->pNext) {
						if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
						   tmp->descURL[urlsize] == '\0' &&
						   memcmp(tmp->st, st, stsize) == 0 &&
						   tmp->st[stsize] == '\0' &&
						   (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
						   tmp->usn[usnsize] == '\0')
							break;
					}
					/* at the exit of the loop above, tmp is null if
					 * no duplicate device was found */
					if(tmp)
						continue;
					tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
					if(!tmp) {
						/* memory allocation error */
						if(error)
							*error = MINISSDPC_MEMORY_ERROR;
						goto error;
					}
					tmp->pNext = devlist;
					tmp->descURL = tmp->buffer;
					tmp->st = tmp->buffer + 1 + urlsize;
					tmp->usn = tmp->st + 1 + stsize;
					memcpy(tmp->buffer, descURL, urlsize);
					tmp->buffer[urlsize] = '\0';
					memcpy(tmp->st, st, stsize);
					tmp->buffer[urlsize+1+stsize] = '\0';
					if(usn != NULL)
						memcpy(tmp->usn, usn, usnsize);
					tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
					tmp->scope_id = scope_id;
					devlist = tmp;
				}
			}
		} while(n > 0);
		if(ipv6) {
			/* switch linklocal flag */
			if(linklocal) {
				linklocal = 0;
				--deviceIndex;
			} else {
				linklocal = 1;
			}
		}
	}
error:
	closesocket(sudp);
	return devlist;
}
Ejemplo n.º 5
0
/* connecthostport()
 * return a socket connected (TCP) to the host and port
 * or -1 in case of error */
SOCKET connecthostport(const char * host, unsigned short port,
                       unsigned int scope_id)
{
	SOCKET s;
	int n;
#ifdef USE_GETHOSTBYNAME
	struct sockaddr_in dest;
	struct hostent *hp;
#else /* #ifdef USE_GETHOSTBYNAME */
	char tmp_host[MAXHOSTNAMELEN+1];
	char port_str[8];
	struct addrinfo *ai, *p;
	struct addrinfo hints;
#endif /* #ifdef USE_GETHOSTBYNAME */
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
	struct timeval timeout;
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */

#ifdef USE_GETHOSTBYNAME
	hp = gethostbyname(host);
	if(hp == NULL)
	{
		herror(host);
		return INVALID_SOCKET;
	}
	memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
	memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
	s = socket(PF_INET, SOCK_STREAM, 0);
	if(ISINVALID(s))
	{
		PRINT_SOCKET_ERROR("socket");
		return INVALID_SOCKET;
	}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
	/* setting a 3 seconds timeout for the connect() call */
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;
	if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
	{
		PRINT_SOCKET_ERROR("setsockopt SO_RCVTIMEO");
	}
	timeout.tv_sec = 3;
	timeout.tv_usec = 0;
	if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
	{
		PRINT_SOCKET_ERROR("setsockopt SO_SNDTIMEO");
	}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
	dest.sin_family = AF_INET;
	dest.sin_port = htons(port);
	n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
#ifdef MINIUPNPC_IGNORE_EINTR
	/* EINTR The system call was interrupted by a signal that was caught
	 * EINPROGRESS The socket is nonblocking and the connection cannot
	 *             be completed immediately. */
	while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
	{
		socklen_t len;
		fd_set wset;
		int err;
		FD_ZERO(&wset);
		FD_SET(s, &wset);
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
		timeout.tv_sec = 3;
		timeout.tv_usec = 0;
		n = select(s + 1, NULL, &wset, NULL, &timeout);
#else
		n = select(s + 1, NULL, &wset, NULL, NULL);
#endif
		if(n == -1 && errno == EINTR)
			continue;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
		if(n == 0) {
			errno = ETIMEDOUT;
			n = -1;
			break;
		}
#endif
		/*len = 0;*/
		/*n = getpeername(s, NULL, &len);*/
		len = sizeof(err);
		if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
			PRINT_SOCKET_ERROR("getsockopt");
			closesocket(s);
			return INVALID_SOCKET;
		}
		if(err != 0) {
			errno = err;
			n = -1;
		}
	}
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
	if(n<0)
	{
		PRINT_SOCKET_ERROR("connect");
		closesocket(s);
		return INVALID_SOCKET;
	}
#else /* #ifdef USE_GETHOSTBYNAME */
	/* use getaddrinfo() instead of gethostbyname() */
	memset(&hints, 0, sizeof(hints));
	/* hints.ai_flags = AI_ADDRCONFIG; */
#ifdef AI_NUMERICSERV
	hints.ai_flags = AI_NUMERICSERV;
#endif
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
	/* hints.ai_protocol = IPPROTO_TCP; */
	snprintf(port_str, sizeof(port_str), "%hu", port);
	if(host[0] == '[')
	{
		/* literal ip v6 address */
		int i, j;
		for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
		{
			tmp_host[i] = host[j];
			if(0 == strncmp(host+j, "%25", 3))	/* %25 is just url encoding for '%' */
				j+=2;							/* skip "25" */
		}
		tmp_host[i] = '\0';
	}
	else
	{
		strncpy(tmp_host, host, MAXHOSTNAMELEN);
	}
	tmp_host[MAXHOSTNAMELEN] = '\0';
	n = getaddrinfo(tmp_host, port_str, &hints, &ai);
	if(n != 0)
	{
#ifdef _WIN32
		fprintf(stderr, "getaddrinfo() error : %d\n", n);
#else
		fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
#endif
		return INVALID_SOCKET;
	}
	s = INVALID_SOCKET;
	for(p = ai; p; p = p->ai_next)
	{
		if(!ISINVALID(s))
			closesocket(s);
		s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
		if(ISINVALID(s))
			continue;
		if(p->ai_addr->sa_family == AF_INET6 && scope_id > 0) {
			struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)p->ai_addr;
			addr6->sin6_scope_id = scope_id;
		}
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
		/* setting a 3 seconds timeout for the connect() call */
		timeout.tv_sec = 3;
		timeout.tv_usec = 0;
		if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
		{
			PRINT_SOCKET_ERROR("setsockopt");
		}
		timeout.tv_sec = 3;
		timeout.tv_usec = 0;
		if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
		{
			PRINT_SOCKET_ERROR("setsockopt");
		}
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
		n = connect(s, p->ai_addr, MSC_CAST_INT p->ai_addrlen);
#ifdef MINIUPNPC_IGNORE_EINTR
		/* EINTR The system call was interrupted by a signal that was caught
		 * EINPROGRESS The socket is nonblocking and the connection cannot
		 *             be completed immediately. */
		while(n < 0 && (errno == EINTR || errno == EINPROGRESS))
		{
			socklen_t len;
			fd_set wset;
			int err;
			FD_ZERO(&wset);
			FD_SET(s, &wset);
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
			timeout.tv_sec = 3;
			timeout.tv_usec = 0;
			n = select(s + 1, NULL, &wset, NULL, &timeout);
#else
			n = select(s + 1, NULL, &wset, NULL, NULL);
#endif
			if(n == -1 && errno == EINTR)
				continue;
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
			if(n == 0) {
				errno = ETIMEDOUT;
				n = -1;
				break;
			}
#endif
			/*len = 0;*/
			/*n = getpeername(s, NULL, &len);*/
			len = sizeof(err);
			if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
				PRINT_SOCKET_ERROR("getsockopt");
				closesocket(s);
				freeaddrinfo(ai);
				return INVALID_SOCKET;
			}
			if(err != 0) {
				errno = err;
				n = -1;
			}
		}
#endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
		if(n >= 0)	/* connect() was successful */
			break;
	}
	freeaddrinfo(ai);
	if(ISINVALID(s))
	{
		PRINT_SOCKET_ERROR("socket");
		return INVALID_SOCKET;
	}
	if(n < 0)
	{
		PRINT_SOCKET_ERROR("connect");
		closesocket(s);
		return INVALID_SOCKET;
	}
#endif /* #ifdef USE_GETHOSTBYNAME */
	return s;
}
Ejemplo n.º 6
0
static int send_authcontext_request(am_net_t *conn, const char *realm, char **token) {
    static const char *thisfunc = "send_authcontext_request():";
    size_t post_sz, post_data_sz;
    char *post = NULL, *post_data = NULL;
    int status = AM_ERROR;
    struct request_data *req_data;

    if (conn == NULL || conn->data == NULL || token == NULL ||
            !ISVALID(realm)) return AM_EINVAL;

    req_data = (struct request_data *) conn->data;

    post_data_sz = am_asprintf(&post_data,
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            "<RequestSet vers=\"1.0\" svcid=\"auth\" reqid=\"0\">"
            "<Request><![CDATA["
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><AuthContext version=\"1.0\">"
            "<Request authIdentifier=\"0\">"
            "<NewAuthContext orgName=\"%s\"/></Request></AuthContext>]]>"
            "</Request></RequestSet>",
            realm);
    if (post_data == NULL) return AM_ENOMEM;

    post_sz = am_asprintf(&post, "POST %s/authservice HTTP/1.1\r\n"
            "Host: %s:%d\r\n"
            "User-Agent: "MODINFO"\r\n"
            "Accept: text/xml\r\n"
            "Connection: Keep-Alive\r\n"
            "Content-Type: text/xml; charset=UTF-8\r\n"
            "Content-Length: %d\r\n\r\n"
            "%s", conn->uv.path, conn->uv.host, conn->uv.port, post_data_sz, post_data);
    if (post == NULL) {
        free(post_data);
        return AM_ENOMEM;
    }

#ifdef DEBUG
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
    AM_LOG_DEBUG(conn->instance_id, "%s sending %d bytes", thisfunc, post_sz);
#endif
    if (conn->log != NULL) {
#ifdef DEBUG
        conn->log("%s sending %d bytes:\n%s", thisfunc, post_sz, post);
#else
        conn->log("%s sending %d bytes", thisfunc, post_sz);
#endif                
    }

    status = am_net_write(conn, post, post_sz);
    free(post_data);
    free(post);

    if (status == AM_SUCCESS) {
        wait_for_event(req_data->event, 0);
    }

    AM_LOG_DEBUG(conn->instance_id, "%s response status code: %d\n%s",
            thisfunc, conn->http_status, LOGEMPTY(req_data->data));
    if (conn->log != NULL) {
        conn->log("%s response status code: %d\n%s", thisfunc,
                conn->http_status, LOGEMPTY(req_data->data));
    }

    if (status == AM_SUCCESS && conn->http_status == 200 && ISVALID(req_data->data)) {
        char *begin = strstr(req_data->data, "Response authIdentifier=\"");
        if (begin != NULL) {
            char *end = strstr(begin + 25, "\"");
            if (end != NULL) {
                *token = strndup(begin + 25, end - begin - 25);
            }
        }
        if (ISINVALID(*token)) {
            status = AM_NOT_FOUND;
        }

        if (status == AM_SUCCESS && ISVALID(conn->req_headers)) {
            am_request_t req_temp;
            int decode_status;

            memset(&req_temp, 0, sizeof(am_request_t));
            req_temp.token = strdup(*token);

            decode_status = am_session_decode(&req_temp);
            if (decode_status == AM_SUCCESS && req_temp.session_info.error == AM_SUCCESS) {

                if (ISVALID(req_temp.session_info.si)) {
                    am_asprintf(&conn->req_headers, "%s%s\r\n", conn->req_headers, req_temp.session_info.si);
                } else {
                    am_free(conn->req_headers);
                    conn->req_headers = NULL;
                }

                AM_LOG_DEBUG(conn->instance_id, "%s app token SI: %s, S1: %s", thisfunc,
                        LOGEMPTY(req_temp.session_info.si), LOGEMPTY(req_temp.session_info.s1));
            }
            am_request_free(&req_temp);
        }
    }

    AM_LOG_DEBUG(conn->instance_id, "%s status: %s", thisfunc, am_strerror(status));
    am_free(req_data->data);
    req_data->data = NULL;
    return status;
}