/** * LANHostConfigManagement:1 Action: DeleteIPRouter. * * Deletes the default router. * This action only affects the default router, not all routers like defined in the spec. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int DeleteIPRouter( struct Upnp_Action_Request *ca_event ) { char *parmList[] = { ROUTE_COMMAND, "del", "default", "gw", NULL, NULL }; int status; if ( ( parmList[4] = GetFirstDocumentItem( ca_event->ActionRequest, "NewIPRouters" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // run route del command status = RunCommand( ROUTE_COMMAND, parmList ); if ( !status ) ParseResult( ca_event, "" ); else { trace( 2, "DeleteIPRouter: Route command returned error: %d", status ); addErrorData( ca_event, 702, "ValueSpecifiedIsInvalid" ); } } else InvalidArgs( ca_event ); free( parmList[4] ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetDHCPServerConfigurable. * * Set dhcp server configuration flag. * It fails if CheckLanHostConfigFiles fails. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetDHCPServerConfigurable( struct Upnp_Action_Request *ca_event ) { char *configurable; int config; if ( ( configurable = GetFirstDocumentItem( ca_event->ActionRequest, "NewDHCPServerConfigurable" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { config = resolveBoolean( configurable ); // if user is setting configurable to true, check that all necessary files are installed if ( config && CheckLanHostConfigFiles() ) { // init failed, send action failed response ca_event->ErrCode = 501; strcpy( ca_event->ErrStr, "Action Failed" ); ca_event->ActionResult = NULL; } else { lanHostConfig.DHCPServerConfigurable = config; ParseResult( ca_event, "" ); } } else InvalidArgs( ca_event ); free( configurable ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetAddressRange. * * Sets the address range dhcp server will give out. * * @todo Maybe we should use the 3 first parts of the ip address to set the ip address of this router? * Now they are just ignored. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetAddressRange( struct Upnp_Action_Request *ca_event ) { char *parmList[] = { g_vars.uciCmd, "set", NULL, NULL }; char *start_addr, *limit_addr; char command[MAX_IP_LAST_PART+15]; char start[MAX_IP_LAST_PART], limit[MAX_IP_LAST_PART]; start_addr = GetFirstDocumentItem( ca_event->ActionRequest, "NewMinAddress" ); limit_addr = GetFirstDocumentItem( ca_event->ActionRequest, "NewMaxAddress" ); if ( start_addr && limit_addr && ( GetNbSoapParameters( ca_event->ActionRequest ) == 2 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // parse last part of both ip addresses if ( ParseAddressRange( ca_event, start, limit, start_addr, limit_addr ) ) return ca_event->ErrCode; snprintf( command, MAX_IP_LAST_PART+15, "dhcp.lan.start=%s", start ); parmList[2] = command; RunCommand( g_vars.uciCmd, parmList ); snprintf( command, MAX_IP_LAST_PART+15, "dhcp.lan.limit=%s", limit ); parmList[2] = command; RunCommand( g_vars.uciCmd, parmList ); UciCommit(); DnsmasqRestart(); } else InvalidArgs( ca_event ); if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); free( start_addr ); free( limit_addr ); return ca_event->ErrCode; }
void Test_AddAnyPortMapping(void) { struct Upnp_Action_Request event; char *port = NULL; int result; strcpy(event.ActionName,"AddAnyPortMapping"); strcpy(event.DevUDN,"00:22132:24324"); strcpy(event.ServiceID,"99"); // Add new port mapping event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_ok_xml); CU_ASSERT(AddAnyPortMapping(&event) == 0); port = GetFirstDocumentItem(event.ActionResult, "NewReservedPort"); CU_ASSERT(strcmp(port, "100") == 0); // Add it again event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_reserved_xml); result = AddAnyPortMapping(&event); CU_ASSERT(result == 0); port = GetFirstDocumentItem(event.ActionResult, "NewReservedPort"); CU_ASSERT(strcmp(port, "100") != 0); // Wildcard in internal client event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_wild_card_in_internal_client_xml); CU_ASSERT(AddAnyPortMapping(&event) == 715); // Wildcard in external port event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_wild_card_in_external_port_xml); result = AddAnyPortMapping(&event); CU_ASSERT(result == 716); // Different internal and external port values event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_different_port_values_xml); CU_ASSERT(AddAnyPortMapping(&event) == 724); // Missing parameter event.ActionRequest = ixmlParseBuffer(add_any_port_mapping_missing_parameter_xml); CU_ASSERT(AddAnyPortMapping(&event) == 402); }
/** * LANHostConfigManagement:1 Action: SetIPRouter. * * Sets the default router. * This action only affects the default router, not all routers like defined in the spec. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetIPRouter( struct Upnp_Action_Request *ca_event ) { char *parmList[] = { ROUTE_COMMAND, NULL, "default", "gw", NULL, NULL }; char addr[LINE_LEN]; char *new_router; int status; if ( ( new_router = GetFirstDocumentItem( ca_event->ActionRequest, "NewIPRouters" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // if default gateway already exists, delete it if ( GetDefaultGateway( addr ) ) { // check that new gateway is different than current if ( strcmp( new_router, addr ) == 0 ) { addErrorData( ca_event, 701, "ValueAlreadySpecified" ); trace( 2, "SetIPRouter: new default gw '%s' is the same as current one '%s'", new_router, addr ); free( new_router ); return ca_event->ErrCode; } parmList[1] = "del"; parmList[4] = addr; RunCommand( ROUTE_COMMAND, parmList ); } // add new default gw parmList[1] = "add"; parmList[4] = new_router; status = RunCommand( ROUTE_COMMAND, parmList ); if ( !status ) ParseResult( ca_event, "" ); else { trace( 2, "SetIPRouter: Route command returned error: %d", status ); addErrorData( ca_event, 501, "Action Failed" ); } } else InvalidArgs( ca_event ); free( new_router ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetDomainName. * * Uses uci option dhcp.@dnsmasq[0].domain * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetDomainName( struct Upnp_Action_Request *ca_event ) { FILE *cmd = NULL; char *domainName; char setdomain_cmd[LINE_LEN]; regex_t reg_domain; if ( ( domainName = GetFirstDocumentItem( ca_event->ActionRequest, "NewDomainName" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // sanitize input regcomp(®_domain, REGEX_DOMAIN_NAME, REG_EXTENDED); if( regexec( ®_domain, domainName, 0, 0, 0 ) != 0 ) { trace( 1, "SetDomainName: Domain Name contains invalid characters: '%s'.", domainName ); InvalidArgs( ca_event ); regfree(®_domain); return ca_event->ErrCode; } regfree(®_domain); snprintf( setdomain_cmd, LINE_LEN, "uci set dhcp.@dnsmasq[0].domain=%s", domainName ); cmd = popen( setdomain_cmd, "r" ); if ( cmd == NULL ) { trace( 1, "SetDomainName: setting Domain Name failed." ); addErrorData( ca_event, 501, "Action Failed" ); return ca_event->ErrCode; } UciCommit(); NetworkCommand( SERVICE_RESTART ); ParseResult( ca_event, "" ); } else InvalidArgs( ca_event ); if ( cmd ) pclose( cmd ); free( domainName ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetDHCPRelay. * * Change dhcp mode between relay server and normal dhcp server. * Start / Stop dhcrelay and dnsmasq accordingly. * * @todo check that dhcrelay is installed in the system * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetDHCPRelay( struct Upnp_Action_Request *ca_event ) { char *dhcrelay; int b_dhcrelay; if ( ( dhcrelay = GetFirstDocumentItem( ca_event->ActionRequest, "NewDHCPRelay" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; b_dhcrelay = resolveBoolean( dhcrelay ); if ( b_dhcrelay != lanHostConfig.dhcrelay ) { if ( b_dhcrelay ) { DnsmasqCommand( SERVICE_STOP ); DhcrelayStart(); } else { DhcrelayStop(); DnsmasqCommand( SERVICE_START ); } lanHostConfig.dhcrelay = b_dhcrelay; } } else InvalidArgs( ca_event ); if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); free( dhcrelay ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetSubnetMask. * * Set the subnet mask of the LAN. * Uses uci option network.lan.netmask. * After setting the parameter network is restarted. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetSubnetMask( struct Upnp_Action_Request *ca_event ) { char *subnet_mask; char command[INET6_ADDRSTRLEN]; char *args[] = { g_vars.uciCmd, "set", NULL, NULL }; regex_t reg_ip; if ( ( subnet_mask = GetFirstDocumentItem( ca_event->ActionRequest, "NewSubnetMask" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // sanitize input regcomp(®_ip, REGEX_IP_LASTBYTE, REG_EXTENDED); if( regexec( ®_ip, subnet_mask, 0, 0, 0 ) != 0 ) { trace( 1, "SetDomainName: subnet mask contains invalid characters: '%s'.", subnet_mask ); InvalidArgs( ca_event ); regfree( ®_ip ); return ca_event->ErrCode; } regfree( ®_ip ); snprintf( command, INET6_ADDRSTRLEN, "network.lan.netmask=%s", subnet_mask ); args[2] = command; RunCommand( g_vars.uciCmd, args ); UciCommit(); NetworkCommand( SERVICE_RESTART ); } else InvalidArgs( ca_event ); if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: DeleteReservedAddress. * * Deletes specified ip-address from reserved addresses if it can be found. * This action only takes one ip-address at a time, not a comma separated list. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int DeleteReservedAddress( struct Upnp_Action_Request *ca_event ) { char command[COMMAND_LEN]; char *del_addr; FILE *cmd; char line[MAX_CONFIG_LINE]; int i = 0; int deleted = FALSE; if ( ( ( del_addr = GetFirstDocumentItem( ca_event->ActionRequest, "NewReservedAddresses" ) ) == NULL ) || ( GetNbSoapParameters( ca_event->ActionRequest ) != 1 ) ) { InvalidArgs( ca_event ); return ca_event->ErrCode; } if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // added MAX_RESERVED_ADDRESS as precaution, if under some conditions uci returns always something // if that is reached, give internal error while ( i < MAX_RESERVED_ADDRESS ) { sprintf( command, "uci -q get dhcp.@host[%d].ip", i ); cmd = popen( command, "r" ); if ( cmd == NULL ) { trace( 1, "DeleteReservedAddress: Error running command: '%s'", command ); addErrorData( ca_event, 501, "Action Failed" ); break; } if ( fgets( line, MAX_CONFIG_LINE, cmd ) == NULL ) { // returned nothing, no more hosts defined pclose( cmd ); break; } pclose( cmd ); if ( strncmp( line, del_addr, strlen( del_addr ) ) == 0 ) { sprintf( command, "uci -q delete dhcp.@host[%d]", i ); cmd = popen( command, "r" ); if ( cmd == NULL ) { trace( 1, "DeleteReservedAddress: Error running command: '%s'", command ); addErrorData( ca_event, 501, "Action Failed" ); } else { // entry successfully deleted deleted = TRUE; UciCommit(); DnsmasqRestart(); pclose( cmd ); } break; } i++; } if ( i == MAX_RESERVED_ADDRESS ) { trace( 1, "DeleteReservedAddress: Internal error in function." ); addErrorData( ca_event, 501, "Action Failed" ); } if ( deleted == FALSE ) { trace( 2, "DeleteReservedAddress: Can't find address to delete: '%s'.", del_addr ); addErrorData( ca_event, 702, "ValueSpecifiedIsInvalid" ); } if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); if ( cmd ) pclose( cmd ); free( del_addr ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetReservedAddress. * * Sets the reserved addesses, that dhcp server won't give to clients. * Old values will be deleted before the new list is applied. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetReservedAddress( struct Upnp_Action_Request *ca_event ) { char command[COMMAND_LEN]; FILE *cmd; char line[MAX_CONFIG_LINE]; char *all_addr, *addr; char *add_args[] = { g_vars.uciCmd, "-q", "add", "dhcp", "host", NULL }; char *set_args[] = { g_vars.uciCmd, "-q", "set", NULL, NULL }; char *del_args[] = { g_vars.uciCmd, "-q", "delete", "dhcp.@host[0]", NULL }; int i=0; if ( ( ( all_addr = GetFirstDocumentItem( ca_event->ActionRequest, "NewReservedAddresses" ) ) == NULL ) || ( GetNbSoapParameters( ca_event->ActionRequest ) != 1 ) ) { InvalidArgs( ca_event ); return ca_event->ErrCode; } if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // delete all hosts while ( i < MAX_RESERVED_ADDRESS ) { sprintf( command, "uci -q get dhcp.@host[0]" ); cmd = popen( command, "r" ); if ( cmd == NULL ) { trace( 1, "SetReservedAddress: Error running command: '%s'", command ); addErrorData( ca_event, 501, "Action Failed" ); break; } // if nothing is returned, we have removed all hosts if ( fgets( line, MAX_CONFIG_LINE, cmd ) == NULL ) { pclose( cmd ); break; } pclose( cmd ); RunCommand( g_vars.uciCmd, del_args ); i++; } // if deleting was successful then add new hosts if ( ca_event->ErrCode == 0 ) { addr = strtok( all_addr, "," ); while ( addr != NULL ) { // add new host RunCommand( g_vars.uciCmd, add_args ); // set host values set_args[3] = "dhcp.@host[-1].name=IGDv2"; RunCommand( g_vars.uciCmd, set_args ); set_args[3] = "dhcp.@host[-1].mac=00:00:00:00:00:00"; RunCommand( g_vars.uciCmd, set_args ); sprintf( command, "dhcp.@host[-1].ip=%s", addr ); set_args[3] = command; RunCommand( g_vars.uciCmd, set_args ); addr = strtok( NULL, "," ); } } if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); free( all_addr ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: DeleteDNSServer. * * Deletes one dns server. * Opens resolv.conf file and a temp file. Copies everything except the deleted nameserver from original * file to the temp file. The temp file is copied over the original file. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int DeleteDNSServer( struct Upnp_Action_Request *ca_event ) { FILE *file = NULL, *new_file = NULL; char line[MAX_CONFIG_LINE]; char dns[INET6_ADDRSTRLEN]; char *dns_to_delete = NULL; regex_t nameserver; regmatch_t submatch[SUB_MATCH]; int dns_found = 0; regcomp( &nameserver, REGEX_NAMESERVER, REG_EXTENDED ); ca_event->ErrCode = 0; if ( ( dns_to_delete = GetFirstDocumentItem( ca_event->ActionRequest, "NewDNSServers" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; file = fopen( g_vars.resolvConf, "r" ); new_file = fopen( RESOLV_CONF_TMP, "w" ); if ( file == NULL || new_file == NULL ) { if ( file == NULL ) trace( 1, "Failed to open resolv.conf at: %s.", g_vars.resolvConf ); if ( new_file == NULL ) trace( 1, "Failed to open temp resolv.conf: %s.", RESOLV_CONF_TMP ); addErrorData( ca_event, 501, "Action Failed" ); } else { while ( fgets( line, MAX_CONFIG_LINE, file ) != NULL ) { if ( regexec( &nameserver, line, SUB_MATCH, submatch, 0 ) == 0 ) { // nameserver found, get it strncpy( dns, &line[submatch[1].rm_so], min( submatch[1].rm_eo-submatch[1].rm_so, INET6_ADDRSTRLEN ) ); dns[min( submatch[1].rm_eo-submatch[1].rm_so, INET6_ADDRSTRLEN-1 )] = 0; // if this one needs to be deleted, then continue while loop if ( strncmp( dns, dns_to_delete, INET6_ADDRSTRLEN ) == 0 ) { dns_found = 1; continue; } } // line isn't a nameserver or not the nameserver we want to delete, adding it to the temp file fputs( line, new_file ); } if ( dns_found ) { // operation was successful // replace the real file with our temp file if ( remove( g_vars.resolvConf ) ) { trace( 1, "DeleteDNSServer: removing resolv.conf failed: '%s'.", g_vars.resolvConf ); addErrorData( ca_event, 501, "Action Failed" ); } if ( rename( RESOLV_CONF_TMP, g_vars.resolvConf ) ) { trace( 1, "DeleteDNSServer: renaming resolv.conf failed, old: '%s' new '%s'.", RESOLV_CONF_TMP, g_vars.resolvConf ); addErrorData( ca_event, 501, "Action Failed" ); } } else { trace( 2, "DeleteDNSServer: dns server not found: '%s'.", dns_to_delete ); addErrorData( ca_event, 702, "ValueSpecifiedIsInvalid" ); } } } else InvalidArgs( ca_event ); if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); regfree( &nameserver ); if ( file ) fclose( file ); if ( new_file ) fclose( new_file ); free( dns_to_delete ); return ca_event->ErrCode; }
/** * LANHostConfigManagement:1 Action: SetDNSServer. * * Sets dns servers. * Opens resolv.conf file and a temp file. Copies all but nameservers from original * file to the temp file. Adds new nameservers to the temp file. Copies the temp file * over the original file. * * @param ca_event Upnp event struct. * @return Upnp error code. */ int SetDNSServer( struct Upnp_Action_Request *ca_event ) { FILE *file = NULL, *new_file = NULL; char line[MAX_CONFIG_LINE]; char *dns = NULL; char *dns_list = NULL; regex_t nameserver; regmatch_t submatch[SUB_MATCH]; regcomp( &nameserver, REGEX_NAMESERVER, REG_EXTENDED ); ca_event->ErrCode = 0; if ( ( dns_list = GetFirstDocumentItem( ca_event->ActionRequest, "NewDNSServers" ) ) && ( GetNbSoapParameters( ca_event->ActionRequest ) == 1 ) ) { if ( CheckDHCPServerConfigurable( ca_event ) ) return ca_event->ErrCode; // open resolv.conf for reading file = fopen( g_vars.resolvConf, "r" ); // and temporary file for writing new_file = fopen( RESOLV_CONF_TMP, "w" ); if ( file == NULL || new_file == NULL ) { if ( file == NULL ) trace( 1, "Failed to open resolv.conf at: %s.", g_vars.resolvConf ); if ( new_file == NULL ) trace( 1, "Failed to open temp resolv.conf: %s.", RESOLV_CONF_TMP ); addErrorData( ca_event, 501, "Action Failed" ); } else { while ( fgets( line, MAX_CONFIG_LINE, file ) != NULL ) { if ( regexec( &nameserver, line, SUB_MATCH, submatch, 0 ) == 0 ) continue; // line isn't a nameserver, adding it to the temp file fputs( line, new_file ); } // add all new nameservers dns = strtok( dns_list, "," ); while ( dns != NULL ) { sprintf( line, "nameserver %s\n", dns ); // check that resulted line syntax is correct if ( regexec( &nameserver, line, SUB_MATCH, submatch, 0 ) == 0 ) { fputs( line, new_file ); } else { InvalidArgs( ca_event ); break; } dns = strtok( NULL, "," ); } if ( ca_event->ErrCode == 0 ) { // operation was successful // replace the real file with our temp file if ( remove( g_vars.resolvConf ) ) { trace( 1, "SetDNSServer: removing resolv.conf failed: '%s'.", g_vars.resolvConf ); addErrorData( ca_event, 501, "Action Failed" ); } if ( rename( RESOLV_CONF_TMP, g_vars.resolvConf ) ) { trace( 1, "SetDNSServer: renaming resolv.conf failed, old: '%s' new '%s'.", RESOLV_CONF_TMP, g_vars.resolvConf ); addErrorData( ca_event, 501, "Action Failed" ); } } } } else InvalidArgs( ca_event ); if ( ca_event->ErrCode == 0 ) ParseResult( ca_event, "" ); regfree( &nameserver ); if ( file ) fclose( file ); if ( new_file ) fclose( new_file ); free( dns_list ); return ca_event->ErrCode; }
/** * this function implements the WANIPv6FirewallControl:updatePinhole action * * @param ca_event The UPnP action request from the control point * @return UPnP error code */ int upnp_wanipv6_updatePinhole(struct Upnp_Action_Request *ca_event) { char internal_client[INET6_ADDRSTRLEN]; char *lease_time=NULL; char *unique_id=NULL; int error = 0; struct pinholev6 * pinhole; if ( (unique_id = GetFirstDocumentItem( ca_event->ActionRequest, "UniqueID") ) && (isStringInteger(unique_id) ) && (lease_time = GetFirstDocumentItem( ca_event->ActionRequest, "NewLeaseTime") ) && (isStringInteger(lease_time) ) && (GetNbSoapParameters(ca_event->ActionRequest) == 2 ) ) { if(!g_vars.ipv6firewallEnabled) { //error 702 firewall disabled errorManagement(ERR_FIREWALL_DISABLED, ca_event); return(ERR_FIREWALL_DISABLED); } if(!g_vars.ipv6inboundPinholeAllowed) { errorManagement(ERR_INBOUND_PINHOLE_NOT_ALLOWED, ca_event); return(ERR_INBOUND_PINHOLE_NOT_ALLOWED); } if(phv6_findPinhole((uint32_t)atoi(unique_id), &pinhole)) { //pinhole found // if Internal port is <1024 and InternalClient is different from control point // control point needs to be authorized if ((( pinhole->internal_port < 1024 && pinhole->internal_port > 0) || !ipv6BinAddrCmp(pinhole->internal_client, &ca_event->CtrlPtIPAddr) ) && ( AuthorizeControlPoint(ca_event, 0, 1) != CONTROL_POINT_NOT_AUTHORIZED )) { trace(1, "Internal port number must be greater than 1023 " "and InternalClient must be same as IP of Control point \ unless control point is authorized. " "internal_port:%i internal_client:%s", pinhole->internal_port, internal_client); errorManagement(ERR_ACTION_NOT_AUTHORIZED, ca_event); error = ERR_ACTION_NOT_AUTHORIZED; } // check that leaseduration is between 1 and 86400 else if ((atoi(lease_time) < 1) || (atoi(lease_time) > 86400)) { trace(1, "lease time must be between 1 and 86400"); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } if(error == 0) { phv6_updatePinhole((uint32_t)atoi(unique_id), (uint32_t)atoi(lease_time)); ParseResult( ca_event, "" ); } }
/** * this function implements the WANIPv6FirewallControl:addPinhole action * * @param ca_event The UPnP action request from the control point * @return UPnP error code */ int upnp_wanipv6_addPinhole(struct Upnp_Action_Request *ca_event) { char *remote_host=NULL; char *remote_port=NULL; char *internal_client=NULL; char *internal_port=NULL; char *protocol=NULL; char *lease_time=NULL; uint32_t UniqueId; int error = 0; if ( (remote_host = GetFirstDocumentItem( ca_event->ActionRequest, "RemoteHost") ) && (remote_port = GetFirstDocumentItem( ca_event->ActionRequest, "RemotePort") ) && (internal_client = GetFirstDocumentItem( ca_event->ActionRequest, "InternalClient") ) && (internal_port = GetFirstDocumentItem( ca_event->ActionRequest, "InternalPort") ) && (protocol = GetFirstDocumentItem( ca_event->ActionRequest, "Protocol") ) && (lease_time = GetFirstDocumentItem( ca_event->ActionRequest, "LeaseTime") ) && (GetNbSoapParameters(ca_event->ActionRequest) == 6 ) ) { if(!g_vars.ipv6firewallEnabled) { //error 702 firewall disabled errorManagement(ERR_FIREWALL_DISABLED, ca_event); return(ERR_FIREWALL_DISABLED); } if(!g_vars.ipv6inboundPinholeAllowed) { //error 703 not authorized errorManagement(ERR_INBOUND_PINHOLE_NOT_ALLOWED, ca_event); return(ERR_INBOUND_PINHOLE_NOT_ALLOWED); } if( (!checkForWildCard(remote_host) && checkIPv6addressUsable(remote_host)==0) ) { //invalid args, not IPv6 adresses trace(1, " RemoteHost: %s \n",remote_host); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(!checkForWildCard(remote_port) && (!isStringInteger(remote_port))) { //invalid args, not a port number trace(1, "Failure in AddPinhole:Invalid Arguments!"); trace(1, " RemotePort: %s \n",remote_port); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(checkForWildCard(internal_client)) { trace(1, " Internal client is wildcarded"); errorManagement(ERR_SRC_ADD_WILDCARD, ca_event); error = ERR_SRC_ADD_WILDCARD; } else if(checkIPv6addressUsable(internal_client)==0) { trace(1, " Internal client : %s",internal_client); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(checkGatewayIPv6Addresses(internal_client)) { trace(1, "Can not use the gateway's IP address"); errorManagement(ERR_ACTION_NOT_AUTHORIZED, ca_event); error = ERR_ACTION_NOT_AUTHORIZED; } else if (!isStringInteger(protocol)) { trace(1, "Invalid protocol:%s", protocol); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if (atoi(protocol) == 65535) { trace(1, "Wild cards not permitted in protocol:%s", protocol); errorManagement(ERR_PROTOCOL_WILDCARD, ca_event); error = ERR_PROTOCOL_WILDCARD; } else if ( (atoi(protocol) != IPPROTO_UDPLITE) && (atoi(protocol) != IPPROTO_UDP) && (atoi(protocol) != IPPROTO_TCP) ) { //error 705 protocol not supported errorManagement(ERR_PROTOCOL_NOT_SUPPORTED, ca_event); error = ERR_PROTOCOL_NOT_SUPPORTED; } // if Internal port is <1024 and InternalClient is different from control point // control point needs to be authorized else if ( ( (atoi(internal_port) < 1024 && atoi(internal_port) > 0) || !ipv6StrAddrCmp(internal_client, &ca_event->CtrlPtIPAddr)) && ( AuthorizeControlPoint(ca_event, 0, 1) != CONTROL_POINT_NOT_AUTHORIZED )) { trace(1, "Internal port number must be greater than 1023 " "and InternalClient must be same as IP of Control point " "unless control point is authorized. " "internal_port:%s internal_client:%s", internal_port, internal_client); errorManagement(ERR_ACTION_NOT_AUTHORIZED, ca_event); error = ERR_ACTION_NOT_AUTHORIZED; } // Check InternalPort parameter else if (checkForWildCard(internal_port)) { trace(1, "Wild cards not permitted in internal port:%s", internal_port); errorManagement(ERR_INTERNAL_PORT_WILDCARD, ca_event); error = ERR_INTERNAL_PORT_WILDCARD; } else if(!isStringInteger(internal_port)) { trace(1, "InternalPort is not a port number:%s", internal_port); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } // check that leaseduration is between 1 and 86400 else if ((atoi(lease_time) < 1) || (atoi(lease_time) > 86400) || !isStringInteger(lease_time)) { trace(1, "lease time must be between 1 and 86400"); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(phv6_existingPinhole(internal_client, remote_host, internal_port, remote_port, protocol, &UniqueId)) { phv6_updatePinhole(UniqueId,(uint32_t)atoi(lease_time)); } //else add the pinhole int the list else if(phv6_addPinhole(internal_client, remote_host, internal_port, remote_port, protocol, (uint32_t)atoi(lease_time), &UniqueId) < 0) { trace(1, "AddPinhole out of memory"); errorManagement(ERR_PINHOLE_SPACE_EXHAUSTED, ca_event); error = ERR_PINHOLE_SPACE_EXHAUSTED; } if(error == 0) { ParseResult( ca_event, "<UniqueID>%i</UniqueID>\n", UniqueId ); } } else { trace(1, "Failure in AddPinhole: Invalid Arguments!"); trace(1, " RemotePort: %s RemoteHost: %s Protocol: %s " "InternalPort: %s InternalClient: %s leaseTime: %s", remote_port, remote_host, protocol, internal_port, internal_client, lease_time); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); } free(remote_host); free(remote_port); free(internal_client); free(internal_port); free(protocol); free(lease_time); return(ca_event->ErrCode); }
/** * this function implements the WANIPv6FirewallControl:getOutboundPinholeTimeOut action * * @param ca_event The UPnP action request from the control point * @return UPnP error code */ int upnp_wanipv6_getOutboundPinholeTimeOut(struct Upnp_Action_Request *ca_event) { char *remote_host=NULL; char *remote_port=NULL; char *internal_client=NULL; char *internal_port=NULL; char *protocol=NULL; int error = 0; if ( (remote_host = GetFirstDocumentItem( ca_event->ActionRequest, "RemoteHost") ) && (remote_port = GetFirstDocumentItem( ca_event->ActionRequest, "RemotePort") ) && (internal_client = GetFirstDocumentItem( ca_event->ActionRequest, "InternalClient") ) && (internal_port = GetFirstDocumentItem( ca_event->ActionRequest, "InternalPort") ) && (protocol = GetFirstDocumentItem( ca_event->ActionRequest, "Protocol") ) && (GetNbSoapParameters(ca_event->ActionRequest) == 5 ) ) { if(!(checkForWildCard(internal_client)) && (checkIPv6addressUsable(internal_client)==0)) { //invalid args, not IPv6 adresses trace(1, "Failure in GetOutboundPinholeTimeout:Invalid Arguments!"); trace(1, " Internal Client: %s \n",internal_client); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(!checkForWildCard(remote_host) && (checkIPv6addressUsable(remote_host)==0)) { //invalid args, not IPv6 adresses trace(1, "Failure in GetOutboundPinholeTimeout:Invalid Arguments!"); trace(1, " RemoteHost: %s \n",remote_host); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(!checkForWildCard(remote_port) && (!isStringInteger(remote_port))) { //invalid args, not a port number trace(1, "Failure in GetOutboundPinholeTimeout:Invalid Arguments!"); trace(1, " RemotePort: %s \n",remote_port); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if(!checkForWildCard(internal_port) && (!isStringInteger(internal_port))) { //invalid args, not a port number trace(1, "Failure in GetOutboundPinholeTimeout:Invalid Arguments!"); trace(1, " InternalPort: %s \n",internal_port); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); error = UPNP_SOAP_E_INVALID_ARGS; } else if ( atoi(protocol) != 65535 &&(atoi(protocol) != IPPROTO_UDPLITE) && (atoi(protocol) != IPPROTO_UDP) && (atoi(protocol) != IPPROTO_TCP)) { //error 705 protocol not supported errorManagement(ERR_PROTOCOL_NOT_SUPPORTED, ca_event); error = ERR_PROTOCOL_NOT_SUPPORTED; } if(error == 0) { int timeout = 0; FILE* timeout_file = NULL; if(atoi(protocol) == IPPROTO_UDPLITE) { timeout_file = fopen( "/proc/sys/net/netfilter/nf_conntrack_udplite_timeout", "r" ); } else if(atoi(protocol) == IPPROTO_UDP) { timeout_file = fopen( "/proc/sys/net/netfilter/nf_conntrack_udp_timeout", "r" ); } else if(atoi(protocol) == IPPROTO_TCP) { timeout_file = fopen( "/proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established", "r" ); } if(timeout_file != NULL) { if(fscanf(timeout_file, "%i",&timeout) != EOF); fclose(timeout_file); } else { timeout_file = fopen( "/proc/sys/net/netfilter/nf_conntrack_generic_timeout", "r" ); if( timeout_file != NULL ) { if(fscanf(timeout_file, "%i",&timeout) != EOF); fclose(timeout_file); } else { //TODO no nf_conntrack module loaded } } ParseResult( ca_event, "<OutboundPinholeTimeout>%i</OutboundPinholeTimeout>\n", timeout ); } } else { trace(1, "Failure in GetOutboundPinholeTimeout:" "Invalid Arguments!"); trace(1, " RemoteHost: %s RemotePort: %s InternalClient: " "%s InternalPort: %s Protocol: ", remote_host, remote_port, internal_client, internal_port, protocol); errorManagement(UPNP_SOAP_E_INVALID_ARGS, ca_event); return UPNP_SOAP_E_INVALID_ARGS; } free(remote_host); free(remote_port); free(internal_client); free(internal_port); free(protocol); return(ca_event->ErrCode); }
int FindAndParseService(IXML_Document *DescDoc, const char *location, const char *serviceType, char **serviceId, char **eventURL, char **controlURL) { unsigned int i; unsigned long length; int found = 0; int ret; #ifdef OLD_FIND_SERVICE_CODE #else /* OLD_FIND_SERVICE_CODE */ unsigned int sindex = 0; #endif /* OLD_FIND_SERVICE_CODE */ char *tempServiceType = NULL; char *baseURL = NULL; const char *base = NULL; char *relcontrolURL = NULL; char *releventURL = NULL; IXML_NodeList *serviceList = NULL; IXML_Element *service = NULL; #ifdef BASEURL baseURL = GetFirstDocumentItem(DescDoc, "URLBase"); if (baseURL) base = baseURL; else base = location; #else base = location; #endif #ifdef OLD_FIND_SERVICE_CODE serviceList = GetFirstServiceList(DescDoc); #else /* OLD_FIND_SERVICE_CODE */ for (sindex = 0; (serviceList = GetNthServiceList(DescDoc , sindex)) != NULL; sindex++) { tempServiceType = NULL; relcontrolURL = NULL; releventURL = NULL; service = NULL; #endif /* OLD_FIND_SERVICE_CODE */ length = ixmlNodeList_length(serviceList); for (i = 0; i < length; i++) { service = (IXML_Element *)ixmlNodeList_item(serviceList, i); tempServiceType = GetFirstElementItem( (IXML_Element *)service, "serviceType"); if (tempServiceType && strcmp(tempServiceType, serviceType) == 0) { Print("Found service: %s\n", serviceType); *serviceId = GetFirstElementItem(service, "serviceId"); Print("serviceId: %s\n", *serviceId); relcontrolURL = GetFirstElementItem(service, "controlURL"); releventURL = GetFirstElementItem(service, "eventSubURL"); *controlURL = malloc(strlen(base) + strlen(relcontrolURL) + 1); if (*controlURL) { ret = UpnpResolveURL(base, relcontrolURL, *controlURL); if (ret != UPNP_E_SUCCESS) Print("Error generating controlURL from %s + %s\n", base, relcontrolURL); } *eventURL = malloc(strlen(base) + strlen(releventURL) + 1); if (*eventURL) { ret = UpnpResolveURL(base, releventURL, *eventURL); if (ret != UPNP_E_SUCCESS) Print("Error generating eventURL from %s + %s\n", base, releventURL); } free(relcontrolURL); free(releventURL); relcontrolURL = NULL; releventURL = NULL; found = 1; break; } free(tempServiceType); tempServiceType = NULL; } free(tempServiceType); tempServiceType = NULL; if (serviceList) ixmlNodeList_free(serviceList); serviceList = NULL; #ifdef OLD_FIND_SERVICE_CODE #else /* OLD_FIND_SERVICE_CODE */ } #endif /* OLD_FIND_SERVICE_CODE */ free(baseURL); return found; }