OSStatus WBKeychainFindGenericPassword(CFTypeRef keychain, CFStringRef service, CFStringRef account, CFStringRef *password, SecKeychainItemRef *itemRef) {
  OSStatus status;
  if (password) *password = NULL;
  char *serviceStr = (char *)__WBCFStringCopyUTF8Characters(service);
  char *accountStr = (char *)__WBCFStringCopyUTF8Characters(account);
  require_action_string(serviceStr != NULL && accountStr != NULL, bail, status = paramErr, "Unable to get service or account characters");

  UInt32 length;
  UTF8Char *passwordStr;
  status = SecKeychainFindGenericPassword(keychain,
                                          (UInt32)strlen(serviceStr), serviceStr,
                                          (UInt32)strlen(accountStr), accountStr,
                                          password ? &length : NULL,
                                          password ? (void **)&passwordStr : NULL,
                                          itemRef);
  if ((noErr == status) && password) {
    *password = CFStringCreateWithBytes(kCFAllocatorDefault, passwordStr, length, kCFStringEncodingUTF8, FALSE);
    SecKeychainItemFreeContent(NULL, passwordStr);
  }

bail:
    if (serviceStr) free(serviceStr);
  if (accountStr) free(accountStr);
  return status;
}
Esempio n. 2
0
int
TunnelIPv6Interface::set_online(bool online)
{
	int ret = 0;

	if (online) {
		syslog(LOG_INFO, "Bringing interface %s online. . .", mInterfaceName.c_str());

		require_action((ret = tunnel_bring_online(mFDRead)) == 0, bail, mLastError = errno);
		require_action(tunnel_is_online(mFDRead), bail, mLastError = errno);

		(void)tunnel_set_hw_address(mFDRead, mHardwareAddress);

		require_action_string(tunnel_is_online(mFDRead), bail, mLastError = errno, "Tunnel went offline unexpectedly!");

		if (!IN6_IS_ADDR_UNSPECIFIED(&mRealmLocalAddress)) {
			(void)tunnel_add_address(mFDRead, mRealmLocalAddress.s6_addr, mRealmLocalPrefixSize);
		}

		std::set<struct in6_addr>::const_iterator iter;
		for (iter = mAddresses.begin(); iter != mAddresses.end(); ++iter) {
			(void)tunnel_add_address(mFDRead, iter->s6_addr, 64);
		}
	} else {
		syslog(LOG_INFO, "Taking interface %s offline. . .", mInterfaceName.c_str());

		require_action((ret = tunnel_bring_offline(mFDRead)) == 0, bail, mLastError = errno);
	}

bail:
	return ret;
}
OSStatus WBKeychainAddInternetPassword(SecKeychainRef keychain, CFStringRef server, CFStringRef domain, CFStringRef account,
                                       CFStringRef path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType,
                                       CFStringRef password, SecKeychainItemRef *itemRef) {
  OSStatus status;

  char *pathStr = NULL;
  char *domainStr = NULL;
  char *serverStr = (char *)__WBCFStringCopyUTF8Characters(server);
  char *accountStr = (char *)__WBCFStringCopyUTF8Characters(account);
  char *passwordStr = (char *)__WBCFStringCopyUTF8Characters(password);
  require_action_string(serverStr != NULL && accountStr != NULL && passwordStr != NULL, bail, status = paramErr, "Unable to get service or account characters");

  /* Get optionals parameters characters */
  pathStr = path ? (char *)__WBCFStringCopyUTF8Characters(path) : NULL;
  domainStr = domain ? (char *)__WBCFStringCopyUTF8Characters(domain) : NULL;

  status = SecKeychainAddInternetPassword(keychain,
                                          (UInt32)strlen(serverStr), serverStr,
                                          domainStr ? (UInt32)strlen(domainStr) : 0, domainStr ? : NULL,
                                          (UInt32)strlen(accountStr), accountStr,
                                          pathStr ? (UInt32)strlen(pathStr) : 0, pathStr ? : NULL,
                                          port, protocol, authenticationType,
                                          (UInt32)strlen(passwordStr), passwordStr,
                                          itemRef);

bail:
    if (serverStr) free(serverStr);
  if (accountStr) free(accountStr);
  if (passwordStr) free(passwordStr);
  if (pathStr) free(pathStr);
  if (domainStr) free(domainStr);
  return status;
}
Esempio n. 4
0
smcp_t
smcp_init(
	smcp_t self, uint16_t port
) {
	SMCP_EMBEDDED_SELF_HOOK;

	require(self != NULL, bail);

	if(port == 0)
		port = COAP_DEFAULT_PORT;

#if SMCP_USE_BSD_SOCKETS
	struct sockaddr_in6 saddr = {
#if SOCKADDR_HAS_LENGTH_FIELD
		.sin6_len		= sizeof(struct sockaddr_in6),
#endif
		.sin6_family	= AF_INET6,
		.sin6_port		= htons(port),
	};
#endif

	// Clear the entire structure.
	memset(self, 0, sizeof(*self));

	// Set up the UDP port for listening.
#if SMCP_USE_BSD_SOCKETS
	uint16_t attempts = 0x7FFF;

	self->mcfd = -1;
	self->fd = -1;
	errno = 0;

	self->fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
	int prev_errno = errno;

	require_action_string(
		self->fd >= 0,
		bail, (
			smcp_release(self),
			self = NULL
		),
		strerror(prev_errno)
	);

	// Keep attempting to bind until we find a port that works.
	while(bind(self->fd, (struct sockaddr*)&saddr, sizeof(saddr)) != 0) {
		// We should only continue trying if errno == EADDRINUSE.
		require_action_string(errno == EADDRINUSE, bail,
			{ DEBUG_PRINTF(CSTR("errno=%d"), errno); smcp_release(
				    self); self = NULL; }, "Failed to bind socket");
		port++;

		// Make sure we aren't in an infinite loop.
		require_action_string(--attempts, bail,
			{ DEBUG_PRINTF(CSTR("errno=%d"), errno); smcp_release(
				    self); self = NULL; }, "Failed to bind socket (ran out of ports)");
Esempio n. 5
0
static DNSStatus	ProcessPreset( int inPreset )
{
    DNSStatus		err;

    require_action_string( ( inPreset > 0 ) && ( inPreset <= gPresetsCount ), exit, err = kDNSBadParamErr, "invalid preset" );

    err = ProcessArgs( gPresets[ inPreset - 1 ].argc, (char **) gPresets[ inPreset - 1 ].argv );

exit:
    return( err );
}
//Call SecKeychainAddGenericPassword to add a new password to the keychain:
OSStatus WBKeychainAddGenericPassword(SecKeychainRef keychain, CFStringRef service, CFStringRef account, CFStringRef password, SecKeychainItemRef *itemRef) {
  OSStatus status;
  char *serviceStr = (char *)__WBCFStringCopyUTF8Characters(service);
  char *accountStr = (char *)__WBCFStringCopyUTF8Characters(account);
  char *passwordStr = (char *)__WBCFStringCopyUTF8Characters(password);
  require_action_string(serviceStr != NULL && accountStr != NULL && passwordStr != NULL, bail, status = paramErr, "Unable to get service or account characters");

  status = SecKeychainAddGenericPassword(keychain,
                                         (UInt32)strlen(serviceStr), serviceStr,
                                         (UInt32)strlen(accountStr), accountStr,
                                         (UInt32)strlen(passwordStr), passwordStr,
                                         itemRef);

bail:
    if (serviceStr) free(serviceStr);
  if (accountStr) free(accountStr);
  if (passwordStr) free(passwordStr);
  return status;
}
Esempio n. 7
0
smcp_status_t
smcp_plat_wait(
	smcp_t self, smcp_cms_t cms
) {
	SMCP_EMBEDDED_SELF_HOOK;
	smcp_status_t ret = SMCP_STATUS_OK;
	struct pollfd polls[4];
	int descriptors_ready;
	int poll_count;

	poll_count = smcp_plat_update_pollfds(self, polls, sizeof(polls)/sizeof(*polls));

	if (poll_count > (int)(sizeof(polls)/sizeof(*polls))) {
		poll_count = sizeof(polls)/sizeof(*polls);
	}

	if(cms >= 0) {
		cms = MIN(cms, smcp_get_timeout(self));
	} else {
		cms = smcp_get_timeout(self);
	}

	errno = 0;

	descriptors_ready = poll(polls, poll_count, cms);

	// Ensure that poll did not fail with an error.
	require_action_string(descriptors_ready != -1,
		bail,
		ret = SMCP_STATUS_ERRNO,
		strerror(errno)
	);

	if (descriptors_ready == 0) {
		ret = SMCP_STATUS_TIMEOUT;
	}

bail:
	return ret;
}
OSStatus WBKeychainFindInternetPassword(CFTypeRef keychain, CFStringRef server, CFStringRef domain, CFStringRef account,
                                        CFStringRef path, UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType,
                                        CFStringRef *password, SecKeychainItemRef *itemRef) {
  OSStatus status;
  if (password) *password = NULL;
  /* Get server and account characters */
  char *pathStr = NULL;
  char *domainStr = NULL;

  char *serverStr = (char *)__WBCFStringCopyUTF8Characters(server);
  char *accountStr = (char *)__WBCFStringCopyUTF8Characters(account);
  require_action_string(serverStr != NULL && accountStr != NULL, bail, status = paramErr, "Unable to get service or account characters");
  /* Get optionals parameters characters */
  pathStr = path ? (char *)__WBCFStringCopyUTF8Characters(path) : NULL;
  domainStr = domain ? (char *)__WBCFStringCopyUTF8Characters(domain) : NULL;

  UInt32 length;
  UTF8Char *passwordStr;
  status =  SecKeychainFindInternetPassword(keychain,
                                            (UInt32)strlen(serverStr), serverStr,
                                            domainStr ? (UInt32)strlen(domainStr) : 0, domainStr ? : NULL,
                                            (UInt32)strlen(accountStr), accountStr,
                                            pathStr ? (UInt32)strlen(pathStr) : 0, pathStr ? : NULL,
                                            port, protocol, authenticationType,
                                            password ? &length : NULL,
                                            password ? (void **)&passwordStr : NULL,
                                            itemRef);
  if ((noErr == status) && password) {
    *password = CFStringCreateWithBytes(kCFAllocatorDefault, passwordStr, length, kCFStringEncodingUTF8, FALSE);
    SecKeychainItemFreeContent(NULL, passwordStr);
  }

bail:
    if (serverStr) free(serverStr);
  if (accountStr) free(accountStr);
  if (pathStr) free(pathStr);
  if (domainStr) free(domainStr);
  return status;
}
Esempio n. 9
0
smcp_status_t smcp_outbound_begin_response(coap_code_t code) {
	smcp_status_t ret = SMCP_STATUS_OK;
	smcp_t const self = smcp_get_current_instance();

	require_action_string(!self->did_respond,
		bail,
		ret = SMCP_STATUS_RESPONSE_NOT_ALLOWED,
		"Attempted to send more than one response!"
	);

	// If we have already started responding, don't bother.
	require(!self->is_responding,bail);

	if(self->is_processing_message)
		self->outbound.next_tid = smcp_inbound_get_msg_id();
	smcp_outbound_begin(self,code,(self->inbound.packet->tt==COAP_TRANS_TYPE_NONCONFIRMABLE)?COAP_TRANS_TYPE_NONCONFIRMABLE:COAP_TRANS_TYPE_ACK);
	self->is_responding = true;

	if(self->is_processing_message)
		smcp_outbound_set_msg_id(smcp_inbound_get_msg_id());

	if(self->is_processing_message) {
#if SMCP_USE_BSD_SOCKETS
		ret = smcp_outbound_set_destaddr(
			self->inbound.saddr,
			self->inbound.socklen
		);
#elif CONTIKI
		ret = smcp_outbound_set_destaddr(
			&self->inbound.toaddr,
			self->inbound.toport
		);
#endif
		require_noerr(ret, bail);
	}
bail:
	return ret;
}
Esempio n. 10
0
smcp_status_t smcp_outbound_begin_response(coap_code_t code) {
	smcp_status_t ret;
	smcp_t const self = smcp_get_current_instance();

	ret = SMCP_STATUS_OK;

	require_action_string(!self->did_respond,
		bail,
		ret = SMCP_STATUS_RESPONSE_NOT_ALLOWED,
		"Attempted to send more than one response!"
	);

	// If we have already started responding, don't bother.
	require_quiet(!self->is_responding, bail);

	if (self->is_processing_message) {
		self->outbound.next_tid = smcp_inbound_get_msg_id();
	}

	ret = smcp_outbound_begin(
		self,
		code,
		(self->inbound.packet->tt==COAP_TRANS_TYPE_NONCONFIRMABLE)?COAP_TRANS_TYPE_NONCONFIRMABLE:COAP_TRANS_TYPE_ACK
	);
	require_noerr(ret, bail);

	self->is_responding = true;

	if (self->is_processing_message) {
		require_noerr(ret=smcp_outbound_set_msg_id(smcp_inbound_get_msg_id()),bail);
	}
bail:
	if (ret != SMCP_STATUS_OK) {
		self->is_responding = false;
	}
	return ret;
}
Esempio n. 11
0
smcp_status_t
smcp_outbound_set_uri(
	const char* uri, char flags
) {
	smcp_status_t ret = SMCP_STATUS_OK;
	smcp_t const self = smcp_get_current_instance();
	SMCP_NON_RECURSIVE struct url_components_s components;
	SMCP_NON_RECURSIVE uint16_t toport;
	SMCP_NON_RECURSIVE char* uri_copy;

	memset((void*)&components, 0, sizeof(components));
	toport = COAP_DEFAULT_PORT;
	smcp_plat_set_session_type(SMCP_SESSION_TYPE_UDP);
	uri_copy = NULL;

	require_action(uri, bail, ret = SMCP_STATUS_INVALID_ARGUMENT);

	{
#if HAVE_ALLOCA
		uri_copy = alloca(strlen(uri) + 1);
		strcpy(uri_copy, uri);
#elif SMCP_AVOID_MALLOC
		// Well, we can't use the stack and we can't
		// use malloc. Let's use what room we have left
		// in the packet buffer, since this is temporary anyway...
		// It helps a bunch that we know the user hasn't written
		// any content yet (because that would be an API violation)
		if (smcp_outbound_get_space_remaining() > strlen(uri) + 8) {
			uri_copy = self->outbound.content_ptr + self->outbound.content_len;

			// The options section may be expanding as we parse this, so
			// we should move ahead by a few bytes. We are helped out
			// by the fact that we will be writing the options in the
			// same order they appear in the URL.
			uri_copy += 8;

			strcpy(uri_copy, uri);
		}
#else
		uri_copy = strdup(uri);
#endif

		require_action(uri_copy != NULL, bail, ret = SMCP_STATUS_MALLOC_FAILURE);

		// Parse the URI.
		require_action_string(
			url_parse(
				uri_copy,
				&components
			),
			bail,
			ret = SMCP_STATUS_URI_PARSE_FAILURE,
			"Unable to parse URL"
		);

		if(!components.protocol && !components.host) {
			// Talking to ourself.
			components.protocol = "coap";
			components.host = "::1";
			toport = smcp_plat_get_port(smcp_get_current_instance());
			flags |= SMCP_MSG_SKIP_AUTHORITY;
		} else if(components.port) {
			toport = (uint16_t)atoi(components.port);
		}

		DEBUG_PRINTF(
			"URI Parse: \"%s\" -> host=\"%s\" port=\"%u\" path=\"%s\"",
			uri,
			components.host,
			toport,
			components.path
		);
	}

	if (components.protocol) {
		smcp_session_type_t session_type = smcp_session_type_from_uri_scheme(components.protocol);
		smcp_plat_set_session_type(session_type);

		if (NULL == components.port) {
			toport = smcp_default_port_from_session_type(session_type);
		}

		if (session_type == SMCP_SESSION_TYPE_NIL) {
			require_action_string(
				self->proxy_url,
				bail,
				ret=SMCP_STATUS_INVALID_ARGUMENT,
				"No proxy URL configured"
			);
			require_action(uri != self->proxy_url,bail,ret = SMCP_STATUS_INVALID_ARGUMENT);

			ret = smcp_outbound_add_option(COAP_OPTION_PROXY_URI, uri, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
			ret = smcp_outbound_set_uri(self->proxy_url,flags);
			goto bail;
		}
	}

	if (!(flags & SMCP_MSG_SKIP_AUTHORITY)) {
		if(components.host && !string_contains_colons(components.host)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_HOST, components.host, SMCP_CSTR_LEN);
			require_noerr(ret, bail);
		}
		if(components.port) {
			ret = smcp_outbound_add_option_uint(COAP_OPTION_URI_PORT, toport);
			require_noerr(ret, bail);
		}
	}


	if ( !(flags & SMCP_MSG_SKIP_DESTADDR)
	  && components.host && components.host[0]!=0
	) {
		ret = smcp_set_remote_sockaddr_from_host_and_port(
			components.host,
			toport
		);
		require_noerr(ret, bail);
	}

	if (components.path) {
		SMCP_NON_RECURSIVE char* component;
		const bool has_trailing_slash = components.path[0]?('/' == components.path[strlen(components.path)-1]):false;

		// Move past any preceding slashes.
		while (components.path[0] == '/') {
			components.path++;
		}

		while (url_path_next_component(&components.path,&component)) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, component, SMCP_CSTR_LEN);
			require_noerr(ret,bail);
		}

		if (has_trailing_slash) {
			ret = smcp_outbound_add_option(COAP_OPTION_URI_PATH, NULL, 0);
			require_noerr(ret,bail);
		}
	}

	if (components.query) {
		SMCP_NON_RECURSIVE char* key;

		while (url_form_next_value(&components.query, &key, NULL)) {
			coap_size_t len = (coap_size_t)strlen(key);

			if (len) {
				ret = smcp_outbound_add_option(COAP_OPTION_URI_QUERY, key, len);
			}
			require_noerr(ret,bail);
		}
	}

bail:
	if(ret) {
		DEBUG_PRINTF("URI Parse failed for URI: \"%s\"",uri);
	}

#if !HAVE_ALLOCA && !SMCP_AVOID_MALLOC
	free(uri_copy);
#endif

	return ret;
}
Esempio n. 12
0
smcp_t
smcp_init(
	smcp_t self, uint16_t port
) {
#if SMCP_EMBEDDED
	smcp_t self = smcp_get_current_instance();
#endif

	require(self != NULL, bail);

	if(port == 0)
		port = COAP_DEFAULT_PORT;

	smcp_sockaddr_t saddr = {
#if SOCKADDR_HAS_LENGTH_FIELD
		.___smcp_len		= sizeof(smcp_sockaddr_t),
#endif
		.___smcp_family	= SMCP_BSD_SOCKETS_NET_FAMILY,
		.smcp_port		= htons(port),
	};

	// Clear the entire structure.
	memset(self, 0, sizeof(*self));

	// Set up the UDP port for listening.
	uint16_t attempts = 0x7FFF;

	self->mcfd = -1;
	self->fd = -1;
	errno = 0;

	self->fd = socket(SMCP_BSD_SOCKETS_NET_FAMILY, SOCK_DGRAM, IPPROTO_UDP);
	int prev_errno = errno;

	require_action_string(
		self->fd >= 0,
		bail, (
			smcp_release(self),
			self = NULL
		),
		strerror(prev_errno)
	);

#if defined(IPV6_V6ONLY) && SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET6
	{
		int value = 0; /* explicitly allow ipv4 traffic too (required on bsd and some debian installations) */
		if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)) < 0)
		{
			DEBUG_PRINTF(CSTR("Socket won't allow IPv4 connections"));
		}
	}
#endif

	// Keep attempting to bind until we find a port that works.
	while(bind(self->fd, (struct sockaddr*)&saddr, sizeof(saddr)) != 0) {
		// We should only continue trying if errno == EADDRINUSE.
		require_action_string(errno == EADDRINUSE, bail,
			{ DEBUG_PRINTF(CSTR("errno=%d"), errno); smcp_release(
				    self); self = NULL; }, "Failed to bind socket");
		port++;

		// Make sure we aren't in an infinite loop.
		require_action_string(--attempts, bail,
			{ DEBUG_PRINTF(CSTR("errno=%d"), errno); smcp_release(
				    self); self = NULL; }, "Failed to bind socket (ran out of ports)");
Esempio n. 13
0
static int ProcessArgs( int argc, char* argv[] )
{
    DNSStatus						err;
    int								i;
    const char *					name;
    const char *					type;
    const char *					domain;
    uint16_t						port;
    const char *					text;
    size_t							textSize;
    DNSBrowserRef					browser;
    DNSResolverFlags				resolverFlags;
    DNSDomainRegistrationType		domainType;
    const char *					label;
    const char *					host;
    const char *					ip;
    unsigned int					b[ 4 ];
    DNSNetworkAddress				addr;
    dns_service_discovery_ref		emulatedRef;

    // Parse the command line arguments (ignore first argument since it's just the program name).

    require_action_string( argc >= 2, exit, err = kDNSBadParamErr, "no arguments specified" );

    for( i = 1; i < argc; ++i )
    {
        if( strcmp( argv[ i ], "-bbd" ) == 0 )
        {
            // 'b'rowse for 'b'rowsing 'd'omains

            fprintf( stdout, "browsing for browsing domains\n" );

            err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser );
            require_noerr_string( err, exit, "create browser failed" );

            err = DNSBrowserStartDomainSearch( browser, 0 );
            require_noerr_string( err, exit, "start domain search failed" );
        }
        else if( strcmp( argv[ i ], "-brd" ) == 0 )
        {
            // 'b'rowse for 'r'egistration 'd'omains

            fprintf( stdout, "browsing for registration domains\n" );

            err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser );
            require_noerr_string( err, exit, "create browser failed" );

            err = DNSBrowserStartDomainSearch( browser, kDNSBrowserFlagRegistrationDomainsOnly );
            require_noerr_string( err, exit, "start domain search failed" );
        }
        else if( strcmp( argv[ i ], "-bs" ) == 0 )
        {
            // 'b'rowse for 's'ervices <type> <domain>

            require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            type 	= argv[ i++ ];
            domain 	= argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "browsing for \"%s.%s\"\n", type, domain );

            err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser );
            require_noerr_string( err, exit, "create browser failed" );

            err = DNSBrowserStartServiceSearch( browser, kDNSBrowserFlagAutoResolve, type, domain );
            require_noerr_string( err, exit, "start service search failed" );
        }
        else if( strcmp( argv[ i ], "-lsi" ) == 0 )
        {
            // 'l'ookup 's'ervice 'i'nstance <name> <type> <domain>

            require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            name 	= argv[ i++ ];
            type 	= argv[ i++ ];
            domain 	= argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "resolving \"%s.%s.%s\"\n", name, type, domain );

            resolverFlags = kDNSResolverFlagOnlyIfUnique |
                            kDNSResolverFlagAutoReleaseByName;
            err = DNSResolverCreate( resolverFlags, name, type, domain, ResolverCallBack, 0, NULL, NULL );
            require_noerr_string( err, exit, "create resolver failed" );
        }
        else if( ( strcmp( argv[ i ], "-rdb" ) == 0 ) || ( strcmp( argv[ i ], "-rdbd" ) == 0 ) )
        {
            // 'r'egister 'd'omain for 'b'rowsing ['d'efault] <domain>

            require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" );
            if( strcmp( argv[ i ], "-rdb" ) == 0 )
            {
                domainType = kDNSDomainRegistrationTypeBrowse;
                label = "";
            }
            else
            {
                domainType = kDNSDomainRegistrationTypeBrowseDefault;
                label = "default ";
            }
            ++i;
            domain = argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "registering \"%s\" as %sbrowse domain\n", domain, label );

            err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL );
            require_noerr_string( err, exit, "create domain registration failed" );
        }
        else if( ( strcmp( argv[ i ], "-rdr" ) == 0 ) || ( strcmp( argv[ i ], "-rdrd" ) == 0 ) )
        {
            // 'r'egister 'd'omain for 'r'egistration ['d'efault] <domain>

            require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" );
            if( strcmp( argv[ i ], "-rdr" ) == 0 )
            {
                domainType = kDNSDomainRegistrationTypeRegistration;
                label = "";
            }
            else
            {
                domainType = kDNSDomainRegistrationTypeRegistrationDefault;
                label = "default ";
            }
            ++i;
            domain = argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "registering \"%s\" as %sregistration domain\n", domain, label );

            err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL );
            require_noerr_string( err, exit, "create domain registration failed" );
        }
        else if( strcmp( argv[ i ], "-rs" ) == 0 )
        {
            // 'r'egister 's'ervice <name> <type> <domain> <port> <txt>

            require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            name 		= argv[ i++ ];
            type 		= argv[ i++ ];
            domain	 	= argv[ i++ ];
            port 		= (uint16_t) atoi( argv[ i++ ] );
            text 		= argv[ i ];
            textSize	= strlen( text );
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text );

            err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, NULL, NULL,
                                         RegistrationCallBack, NULL, NULL );
            require_noerr_string( err, exit, "create registration failed" );
        }
        else if( strcmp( argv[ i ], "-rps" ) == 0 )
        {
            DNSHostRegistrationFlags		hostFlags;

            // 'r'egister 'p'roxy 's'ervice <host> <ip> <name> <type> <domain> <port> <txt>

            require_action_string( argc > ( i + 7 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            host		= argv[ i++ ];
            ip			= argv[ i++ ];
            name 		= argv[ i++ ];
            type 		= argv[ i++ ];
            domain	 	= argv[ i++ ];
            port 		= (uint16_t) atoi( argv[ i++ ] );
            text 		= argv[ i ];
            textSize	= strlen( text );
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }

            sscanf( ip, "%u.%u.%u.%u", &b[ 0 ], &b[ 1 ], &b[ 2 ], &b[ 3 ] );
            addr.addressType 			= kDNSNetworkAddressTypeIPv4;
            addr.u.ipv4.addr.v8[ 0 ] 	= (DNSUInt8) b[ 0 ];
            addr.u.ipv4.addr.v8[ 1 ] 	= (DNSUInt8) b[ 1 ];
            addr.u.ipv4.addr.v8[ 2 ] 	= (DNSUInt8) b[ 2 ];
            addr.u.ipv4.addr.v8[ 3 ] 	= (DNSUInt8) b[ 3 ];

            fprintf( stdout, "registering proxy service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text );

            hostFlags = kDNSHostRegistrationFlagOnlyIfNotFound | kDNSHostRegistrationFlagAutoRenameOnConflict;
            err = DNSHostRegistrationCreate( hostFlags, host, domain, &addr, NULL,
                                             HostRegistrationCallBack, NULL, NULL );
            require_noerr_string( err, exit, "create host registration failed" );

            err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, host, NULL,
                                         RegistrationCallBack, NULL, NULL );
            require_noerr_string( err, exit, "create registration failed" );
        }
        else if( strcmp( argv[ i ], "-rnss" ) == 0 )
        {
            // 'r'egister 'n'o 's'uch 's'ervice <name> <type> <domain>

            require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            name 		= argv[ i++ ];
            type 		= argv[ i++ ];
            domain	 	= argv[ i++ ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "registering no-such-service \"%s.%s.%s\"\n", name, type, domain );

            err = DNSNoSuchServiceRegistrationCreate( 0, name, type, domain, NULL, RegistrationCallBack, NULL, NULL );
            require_noerr_string( err, exit, "create no-such-service registration failed" );
        }
        else if( strcmp( argv[ i ], "-ebs" ) == 0 )
        {
            // 'e'mulated 'b'rowse for 's'ervices <type> <domain>

            require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            type 	= argv[ i++ ];
            domain 	= argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "emulated browsing for \"%s.%s\"\n", type, domain );

            emulatedRef = DNSServiceBrowserCreate( type, domain, EmulatedBrowserCallBack, NULL );
            require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated browser failed" );
        }
        else if( strcmp( argv[ i ], "-ebd" ) == 0 )
        {
            int		registrationOnly;

            // 'e'mulated 'b'rowse for 'd'omains <registration/browse>

            require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            type = argv[ i++ ];
            if( strcmp( type, "registration" ) == 0 )
            {
                registrationOnly = 1;
            }
            else if( strcmp( type, "browse" ) == 0 )
            {
                registrationOnly = 0;
            }
            else
            {
                require_action_string( 0, exit, err = kDNSBadParamErr, "invalid browse type" );
            }
            fprintf( stdout, "emulated browsing for %s domains\n", type );

            emulatedRef = DNSServiceDomainEnumerationCreate( registrationOnly, EmulatedDomainEnumerationCallBack, NULL );
            require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated domain browser failed" );
        }
        else if( strcmp( argv[ i ], "-elsi" ) == 0 )
        {
            // 'e'mulated 'l'ookup 's'ervice 'i'nstance <name> <type> <domain>

            require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            name 	= argv[ i++ ];
            type 	= argv[ i++ ];
            domain 	= argv[ i ];
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "emulated resolving \"%s.%s.%s\"\n", name, type, domain );

            emulatedRef = DNSServiceResolverResolve( name, type, domain, EmulatedResolverCallBack, NULL );
            require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated resolver failed" );
        }
        else if( strcmp( argv[ i ], "-ers" ) == 0 )
        {
            // 'e'mulated 'r'egister 's'ervice <name> <type> <domain> <port> <txt>

            require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" );
            ++i;
            name 		= argv[ i++ ];
            type 		= argv[ i++ ];
            domain	 	= argv[ i++ ];
            port 		= (uint16_t) atoi( argv[ i++ ] );
            text 		= argv[ i ];
            textSize	= strlen( text );
            if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) )
            {
                domain = "local.";
            }
            fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text );

            emulatedRef = DNSServiceRegistrationCreate( name, type, domain, htons( port ), text,
                          EmulatedRegistrationCallBack, NULL );
            require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated registration failed" );
        }
        else if( ( argv[ i ][ 0 ] == '-' ) && isdigit( argv[ i ][ 1 ] ) )
        {
            // Preset

            ProcessPreset( atoi( &argv[ i ][ 1 ] ) );
            err = 0;
            goto exit;
        }
        else if( strcmp( argv[ i ], "-q" ) == 0 )
        {
            // Quiet (no text records)

            gPrintTXTRecords = 0;
        }
        else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) )
        {
            // Help

            Usage();
            err = 0;
            goto exit;
        }
        else
        {
            // Unknown parameter.

            require_action_string( 0, exit, err = kDNSBadParamErr, "unknown parameter" );
            goto exit;
        }
    }

    // Run until control-C'd.

#if( __MACH__ )
    CFRunLoopRun();
#endif

#if( defined( WINVER ) )
    while( !gQuit )
    {
        Sleep( 200 );
    }
#endif

    err = kDNSNoErr;

exit:
    if( err )
    {
        Usage();
    }
    return( err );
}
Esempio n. 14
0
smcp_status_t
smcp_plat_outbound_finish(smcp_t self,const uint8_t* data_ptr, coap_size_t data_len, int flags)
{
	SMCP_EMBEDDED_SELF_HOOK;
	smcp_status_t ret = SMCP_STATUS_FAILURE;
	ssize_t sent_bytes = -1;
	int fd;

#if SMCP_DTLS
	if (smcp_plat_get_session_type() == SMCP_SESSION_TYPE_DTLS) {
		ret = smcp_plat_ssl_outbound_packet_process(self, data_ptr, data_len);
	} else
#endif
	if (smcp_plat_get_session_type() == SMCP_SESSION_TYPE_UDP) {
		fd = smcp_get_current_instance()->plat.fd_udp;

		assert(fd >= 0);

		require(data_len > 0, bail);

#if VERBOSE_DEBUG
		{
			char addr_str[50] = "???";
			uint16_t port = ntohs(smcp_plat_get_remote_sockaddr()->smcp_port);
			SMCP_ADDR_NTOP(addr_str,sizeof(addr_str),&smcp_plat_get_remote_sockaddr()->smcp_addr);
			DEBUG_PRINTF("smcp(%p): Outbound packet to [%s]:%d", self,addr_str,(int)port);
			coap_dump_header(
				SMCP_DEBUG_OUT_FILE,
				"Outbound:\t",
				(struct coap_header_s*)data_ptr,
				(coap_size_t)data_len
			);
		}
#endif

		sent_bytes = sendtofrom(
			fd,
			data_ptr,
			data_len,
			0,
			(struct sockaddr *)smcp_plat_get_remote_sockaddr(),
			sizeof(smcp_sockaddr_t),
			(struct sockaddr *)smcp_plat_get_local_sockaddr(),
			sizeof(smcp_sockaddr_t)
		);

		require_action_string(
			(sent_bytes >= 0),
			bail, ret = SMCP_STATUS_ERRNO, strerror(errno)
		);

		require_action_string(
			(sent_bytes == data_len),
			bail, ret = SMCP_STATUS_FAILURE, "sendto() returned less than len"
		);

		ret = SMCP_STATUS_OK;

	} else {
		ret = SMCP_STATUS_NOT_IMPLEMENTED;
	}
bail:
	return ret;
}
Esempio n. 15
0
smcp_status_t
smcp_plat_bind_to_sockaddr(
	smcp_t self,
	smcp_session_type_t type,
	const smcp_sockaddr_t* sockaddr
) {
	SMCP_EMBEDDED_SELF_HOOK;
	smcp_status_t ret = SMCP_STATUS_FAILURE;
	int fd = -1;

	switch(type) {
#if SMCP_DTLS
	case SMCP_SESSION_TYPE_DTLS:
		break;
#endif
#if SMCP_TCP
	case SMCP_SESSION_TYPE_TCP:
		break;
#endif
#if SMCP_TLS
	case SMCP_SESSION_TYPE_TLS:
		break;
#endif
	case SMCP_SESSION_TYPE_UDP:
		break;

	default:
		ret = SMCP_STATUS_NOT_IMPLEMENTED;
		// Unsupported session type.
		goto bail;
	}

	fd = socket(SMCP_BSD_SOCKETS_NET_FAMILY, SOCK_DGRAM, IPPROTO_UDP);

	require_action_string(fd >= 0, bail, ret = SMCP_STATUS_ERRNO, strerror(errno));

#if defined(IPV6_V6ONLY) && SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET6
	{
		int value = 0; /* explicitly allow ipv4 traffic too (required on bsd and some debian installations) */
		if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)) < 0)
		{
			DEBUG_PRINTF("Setting IPV6_V6ONLY=0 on socket failed (%s)",strerror(errno));
		}
	}
#endif

	require_action_string(
		bind(fd, (struct sockaddr*)sockaddr, sizeof(*sockaddr)) == 0,
		bail,
		ret = SMCP_STATUS_ERRNO,
		strerror(errno)
	);

#ifdef SMCP_RECVPKTINFO
	{	// Handle sockopts.
		int value = 1;
		setsockopt(fd, SMCP_IPPROTO, SMCP_RECVPKTINFO, &value, sizeof(value));
	}
#endif

	// TODO: Fix this!
	switch(type) {
	case SMCP_SESSION_TYPE_UDP:
		self->plat.fd_udp = fd;
		break;

#if SMCP_DTLS
	case SMCP_SESSION_TYPE_DTLS:
		DEBUG_PRINTF("DTLS Port %d", get_port_for_fd(fd));
		self->plat.fd_dtls = fd;
		break;
#endif

	default:
		ret = SMCP_STATUS_NOT_IMPLEMENTED;
		// Unsupported session type.
		goto bail;
	}

	fd = -1;

	ret = SMCP_STATUS_OK;

bail:
	if (fd >= 0) {
		close(fd);
	}
	return ret;
}
Esempio n. 16
-1
smcp_status_t
smcp_plat_process(
	smcp_t self
) {
	SMCP_EMBEDDED_SELF_HOOK;
	smcp_status_t ret = 0;

	int tmp;
	struct pollfd polls[4];
	int poll_count;

	poll_count = smcp_plat_update_pollfds(self, polls, sizeof(polls)/sizeof(polls[0]));

	if (poll_count > (int)(sizeof(polls)/sizeof(*polls))) {
		poll_count = sizeof(polls)/sizeof(*polls);
	}

	errno = 0;

	tmp = poll(polls, poll_count, 0);

	// Ensure that poll did not fail with an error.
	require_action_string(
		errno == 0,
		bail,
		ret = SMCP_STATUS_ERRNO,
		strerror(errno)
	);

	if(tmp > 0) {
		for (tmp = 0; tmp < poll_count; tmp++) {
			if (!polls[tmp].revents) {
				continue;
			} else {
				char packet[SMCP_MAX_PACKET_LENGTH+1];
				smcp_sockaddr_t remote_saddr = {};
				smcp_sockaddr_t local_saddr = {};
				ssize_t packet_len = 0;
				char cmbuf[0x100];
				struct iovec iov = { packet, SMCP_MAX_PACKET_LENGTH };
				struct msghdr msg = {
					.msg_name = &remote_saddr,
					.msg_namelen = sizeof(remote_saddr),
					.msg_iov = &iov,
					.msg_iovlen = 1,
					.msg_control = cmbuf,
					.msg_controllen = sizeof(cmbuf),
				};
				struct cmsghdr *cmsg;

				packet_len = recvmsg(polls[tmp].fd, &msg, 0);

				require_action(packet_len > 0, bail, ret = SMCP_STATUS_ERRNO);

				packet[packet_len] = 0;

				for (
					cmsg = CMSG_FIRSTHDR(&msg);
					cmsg != NULL;
					cmsg = CMSG_NXTHDR(&msg, cmsg)
				) {
					if (cmsg->cmsg_level != SMCP_IPPROTO
						|| cmsg->cmsg_type != SMCP_PKTINFO
					) {
						continue;
					}

					// Preinitialize some of the fields.
					local_saddr = remote_saddr;

#if SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET6
					struct in6_pktinfo *pi = (struct in6_pktinfo *)CMSG_DATA(cmsg);
					local_saddr.smcp_addr = pi->ipi6_addr;
					local_saddr.sin6_scope_id = pi->ipi6_ifindex;

#elif SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET
					struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsg);
					local_saddr.smcp_addr = pi->ipi_addr;
#endif

					local_saddr.smcp_port = htons(get_port_for_fd(polls[tmp].fd));

					self->plat.pktinfo = *pi;
				}

				smcp_set_current_instance(self);
				smcp_plat_set_remote_sockaddr(&remote_saddr);
				smcp_plat_set_local_sockaddr(&local_saddr);

				if (self->plat.fd_udp == polls[tmp].fd) {
					smcp_plat_set_session_type(SMCP_SESSION_TYPE_UDP);

					ret = smcp_inbound_packet_process(self, packet, (coap_size_t)packet_len, 0);
					require_noerr(ret, bail);

#if SMCP_DTLS
				} else if (self->plat.fd_dtls == polls[tmp].fd) {
					smcp_plat_set_session_type(SMCP_SESSION_TYPE_DTLS);
					smcp_plat_ssl_inbound_packet_process(
						self,
						packet,
						(coap_size_t)packet_len
					);
#endif
				}
			}
		}
	}

	smcp_handle_timers(self);

bail:
	smcp_set_current_instance(NULL);
	self->is_responding = false;
	return ret;
}

smcp_status_t
smcp_plat_lookup_hostname(const char* hostname, smcp_sockaddr_t* saddr, int flags)
{
	smcp_status_t ret;
	struct addrinfo hint = {
		.ai_flags		= AI_ADDRCONFIG,
		.ai_family		= AF_UNSPEC,
	};

	struct addrinfo *results = NULL;
	struct addrinfo *iter = NULL;

#if SMCP_BSD_SOCKETS_NET_FAMILY != AF_INET6
	hint.ai_family = SMCP_BSD_SOCKETS_NET_FAMILY;
#endif

	if ((flags & (SMCP_LOOKUP_HOSTNAME_FLAG_IPV4_ONLY|SMCP_LOOKUP_HOSTNAME_FLAG_IPV6_ONLY)) == (SMCP_LOOKUP_HOSTNAME_FLAG_IPV4_ONLY|SMCP_LOOKUP_HOSTNAME_FLAG_IPV6_ONLY)) {
		ret = SMCP_STATUS_INVALID_ARGUMENT;
		goto bail;
	} else if ((flags & SMCP_LOOKUP_HOSTNAME_FLAG_IPV4_ONLY) == SMCP_LOOKUP_HOSTNAME_FLAG_IPV4_ONLY) {
		hint.ai_family = AF_INET;
	} else if ((flags & SMCP_LOOKUP_HOSTNAME_FLAG_IPV6_ONLY) == SMCP_LOOKUP_HOSTNAME_FLAG_IPV6_ONLY) {
		hint.ai_family = AF_INET6;
	}

	memset(saddr, 0, sizeof(*saddr));
	saddr->___smcp_family = SMCP_BSD_SOCKETS_NET_FAMILY;

#if SOCKADDR_HAS_LENGTH_FIELD
	saddr->___smcp_len = sizeof(*saddr);
#endif

	int error = getaddrinfo(hostname, NULL, &hint, &results);

#if SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET6
	if(error && (inet_addr(hostname) != INADDR_NONE)) {
		char addr_v4mapped_str[8 + strlen(hostname)];
		hint.ai_family = AF_INET6;
		hint.ai_flags = AI_ALL | AI_V4MAPPED,
		strcpy(addr_v4mapped_str,"::ffff:");
		strcat(addr_v4mapped_str,hostname);
		error = getaddrinfo(addr_v4mapped_str,
			NULL,
			&hint,
			&results
		);
	}
#endif

	if (EAI_AGAIN == error) {
		ret = SMCP_STATUS_WAIT_FOR_DNS;
		goto bail;
	}

#ifdef TM_EWOULDBLOCK
	if (TM_EWOULDBLOCK == error) {
		ret = SMCP_STATUS_WAIT_FOR_DNS;
		goto bail;
	}
#endif

	require_action_string(
		!error,
		bail,
		ret = SMCP_STATUS_HOST_LOOKUP_FAILURE,
		gai_strerror(error)
	);

	// Move to the first recognized result
	for(iter = results;iter && (iter->ai_family!=AF_INET6 && iter->ai_family!=AF_INET);iter=iter->ai_next);

	require_action(
		iter,
		bail,
		ret = SMCP_STATUS_HOST_LOOKUP_FAILURE
	);

#if SMCP_BSD_SOCKETS_NET_FAMILY==AF_INET6
	if(iter->ai_family == AF_INET) {
		struct sockaddr_in *v4addr = (void*)iter->ai_addr;
		saddr->sin6_addr.s6_addr[10] = 0xFF;
		saddr->sin6_addr.s6_addr[11] = 0xFF;
		memcpy(&saddr->sin6_addr.s6_addr[12], &v4addr->sin_addr.s_addr, 4);
	} else
#endif
	if(iter->ai_family == SMCP_BSD_SOCKETS_NET_FAMILY) {
		memcpy(saddr, iter->ai_addr, iter->ai_addrlen);
	}

	if(SMCP_IS_ADDR_MULTICAST(&saddr->smcp_addr)) {
		smcp_t const self = smcp_get_current_instance();
		check(self->outbound.packet->tt != COAP_TRANS_TYPE_CONFIRMABLE);
		if(self->outbound.packet->tt == COAP_TRANS_TYPE_CONFIRMABLE) {
			self->outbound.packet->tt = COAP_TRANS_TYPE_NONCONFIRMABLE;
		}
	}

	ret = SMCP_STATUS_OK;

bail:
	if(results)
		freeaddrinfo(results);
	return ret;
}