예제 #1
0
smcp_status_t
smcp_set_remote_sockaddr_from_host_and_port(const char* addr_str,uint16_t toport) {
	smcp_status_t ret;
	SMCP_NON_RECURSIVE smcp_sockaddr_t saddr;

	DEBUG_PRINTF("Outbound: Dest host [%s]:%d",addr_str,toport);

	// Check to see if this host is a group we know about.
	if (strcasecmp(addr_str, COAP_MULTICAST_STR_ALLDEVICES) == 0) {
		addr_str = SMCP_COAP_MULTICAST_ALLDEVICES_ADDR;
	}

	ret = smcp_plat_lookup_hostname(addr_str, &saddr);
	require_noerr(ret, bail);

	saddr.smcp_port = htons(toport);

	smcp_plat_set_remote_sockaddr(&saddr);


bail:
	return ret;
}
예제 #2
0
static smcp_status_t
request_handler_new_group_(
	smcp_group_mgr_t self
) {
	smcp_status_t ret = SMCP_STATUS_OK;
	coap_content_type_t content_type;
	coap_size_t content_len;
	char* fqdn = NULL;
	char* addr_cstr = NULL;
	smcp_sockaddr_t saddr = { };
	char* content_ptr = NULL;
	char* key = NULL;
	char* value = NULL;
	smcp_group_t group = NULL;
	char name_str[3] = { };

	content_type = smcp_inbound_get_content_type();
	content_ptr = (char*)smcp_inbound_get_content_ptr();
	content_len = smcp_inbound_get_content_len();

	switch (content_type) {
	case COAP_CONTENT_TYPE_UNKNOWN:
	case COAP_CONTENT_TYPE_TEXT_PLAIN:
	case SMCP_CONTENT_TYPE_APPLICATION_FORM_URLENCODED:
		content_len = 0;
		while(
			url_form_next_value(
				(char**)&content_ptr,
				&key,
				&value
			)
			&& key
			&& value
		) {

			if (strequal_const(key, names[I_FQDN])) {
				fqdn = value;
				DEBUG_PRINTF("new_group: fqdn=\"%s\"", value);
			} else if (strequal_const(key, names[I_ADDR])) {
				addr_cstr = value;
				DEBUG_PRINTF("new_group: addr=\"%s\"", value);
			}
		}
		break;

	default:
		return smcp_outbound_quick_response(HTTP_RESULT_CODE_UNSUPPORTED_MEDIA_TYPE, NULL);
		break;
	}

	if (NULL == addr_cstr) {
		require_action(NULL != fqdn, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);
		addr_cstr = fqdn;
	} else if (NULL == fqdn) {
		fqdn = addr_cstr;
	}

	smcp_plat_lookup_hostname(addr_cstr, &saddr, SMCP_LOOKUP_HOSTNAME_FLAG_DEFAULT);

	group = smcp_group_mgr_new_group(
		self,
		fqdn,
		&saddr.smcp_addr,
		0
	);

	if (!group) {
		return smcp_outbound_quick_response(COAP_RESULT_400_BAD_REQUEST, "(400) Failed to create group");
	}

	// Default to enabled.
	smcp_group_set_enabled(group, true);

	name_str[0] = get_hex_char(group->index >> 4);
	name_str[1] = get_hex_char(group->index >> 0);

	smcp_outbound_begin_response(COAP_RESULT_201_CREATED);
	smcp_outbound_add_option(COAP_OPTION_LOCATION_PATH, name_str, SMCP_CSTR_LEN);
	smcp_outbound_append_content(name_str, SMCP_CSTR_LEN);
	smcp_outbound_send();

bail:
	return ret;
}
예제 #3
0
ssize_t
sendtofrom(
	int fd,
	const void *data, size_t len, int flags,
	const struct sockaddr * saddr_to, socklen_t socklen_to,
	const struct sockaddr * saddr_from, socklen_t socklen_from
)
{
	ssize_t ret = -1;

	if (SMCP_IS_ADDR_MULTICAST(&((smcp_sockaddr_t*)saddr_from)->smcp_addr)) {
		saddr_from = NULL;
		socklen_from = 0;
	}

	if ((socklen_from == 0)
		|| (saddr_from == NULL)
		|| (saddr_from->sa_family != saddr_to->sa_family)
	) {
		ret = sendto(
			fd,
			data,
			len,
			0,
			(struct sockaddr *)saddr_to,
			socklen_to
		);
		check(ret>0);
	} else {
		struct iovec iov = { (void *)data, len };
		uint8_t cmbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
		struct cmsghdr *scmsgp;
		struct msghdr msg = {
			.msg_name = (void*)saddr_to,
			.msg_namelen = socklen_to,
			.msg_iov = &iov,
			.msg_iovlen = 1,
			.msg_control = cmbuf,
			.msg_controllen = sizeof(cmbuf),
		};

#if defined(AF_INET6)
		if (saddr_to->sa_family == AF_INET6) {
			struct in6_pktinfo *pktinfo;
			scmsgp = CMSG_FIRSTHDR(&msg);
			scmsgp->cmsg_level = IPPROTO_IPV6;
			scmsgp->cmsg_type = IPV6_PKTINFO;
			scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
			pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));

			pktinfo->ipi6_addr = ((struct sockaddr_in6*)saddr_from)->sin6_addr;
			pktinfo->ipi6_ifindex = ((struct sockaddr_in6*)saddr_from)->sin6_scope_id;
		} else
#endif

		if (saddr_to->sa_family == AF_INET) {
			struct in_pktinfo *pktinfo;
			scmsgp = CMSG_FIRSTHDR(&msg);
			scmsgp->cmsg_level = IPPROTO_IP;
			scmsgp->cmsg_type = IP_PKTINFO;
			scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
			pktinfo = (struct in_pktinfo *)(CMSG_DATA(scmsgp));

			pktinfo->ipi_spec_dst = ((struct sockaddr_in*)saddr_to)->sin_addr;
			pktinfo->ipi_addr = ((struct sockaddr_in*)saddr_from)->sin_addr;
			pktinfo->ipi_ifindex = 0;
		}

		ret = sendmsg(fd, &msg, flags);

		check(ret > 0);
		check_string(ret >= 0, strerror(errno));
	}

	return ret;
}

smcp_status_t
smcp_plat_set_remote_hostname_and_port(const char* hostname, uint16_t port)
{
	smcp_status_t ret;
	SMCP_NON_RECURSIVE smcp_sockaddr_t saddr;

	DEBUG_PRINTF("Outbound: Dest host [%s]:%d",hostname,port);

#if SMCP_DTLS
	smcp_plat_ssl_set_remote_hostname(hostname);
#endif

	// Check to see if this host is a group we know about.
	if (strcasecmp(hostname, COAP_MULTICAST_STR_ALLDEVICES) == 0) {
		hostname = SMCP_COAP_MULTICAST_ALLDEVICES_ADDR;
	}

	ret = smcp_plat_lookup_hostname(hostname, &saddr, SMCP_LOOKUP_HOSTNAME_FLAG_DEFAULT);
	require_noerr(ret, bail);

	saddr.smcp_port = htons(port);

	smcp_plat_set_remote_sockaddr(&saddr);

bail:
	return ret;
}