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