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; }
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; }
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; }