Пример #1
0
int MapRefItem::parse( const char * &pFormatStr, const char * pEnd, const RewriteMapList * pMaps )
{
    const char * pMapName = pFormatStr + 2;
    const char * pClose = StringTool::findCloseBracket( pMapName, pEnd );
    if ( pClose == pEnd )
    {
        HttpLog::parse_error( s_pCurLine,  "missing '}'" );
        return -1;
    }
    const char * pColon = StringTool::findCharInBracket( pMapName, pClose, ':' );
    if ( pColon == NULL )
    {
        HttpLog::parse_error( s_pCurLine,  "missing ':'" );
        return -1;
    }
    else
    {
        char achName[1024];
        memmove( achName, pMapName, pColon - pMapName );
        achName[pColon - pMapName] = 0;
        RewriteMapList::iterator iter = pMaps->find( achName );
        if ( iter == pMaps->end() )
        {
            HttpLog::parse_error( s_pCurLine,  "rewrite map is not defined" );
            return -1;
        }
        m_pMap = iter.second();
    }
    pFormatStr = pClose + 1;
    const char * pDefault = StringTool::findCharInBracket( pMapName, pClose, '|' );
    if ( pDefault != NULL )
    {
        assert( !m_pDefaultFormat );
        m_pDefaultFormat = new RewriteSubstFormat();
        if ( !m_pDefaultFormat )
        {
            ERR_NO_MEM( "new SubstFormat()" );
            return -1;
        }
        if ( m_pDefaultFormat->parse( pDefault+1, pClose, pMaps ) )
            return -1;
    }
    else
        pDefault = pClose;
    if ( ++pColon == pDefault )
    {
        HttpLog::parse_error( s_pCurLine,  "missing map key" );
        return -1;
    }
    assert( !m_pKeyFormat );
    m_pKeyFormat = new RewriteSubstFormat();
    if ( !m_pKeyFormat )
    {
        ERR_NO_MEM( "new SubstFormat()" );
        return -1;
    }
    return m_pKeyFormat->parse( pColon, pDefault, pMaps );
}
Пример #2
0
int SubstFormat::parse( const char * pCurLine, const char * pFormatStr, const char * pEnd, int isSSI, char varChar )
{
    while(( pFormatStr < pEnd )&&( isspace( *pFormatStr )))
        ++pFormatStr;
    int err = 0;
    char achVarChar[2];
    LinkedObj * pLast = head();
    SubstItem * pItem;
    achVarChar[0] = varChar;
    achVarChar[1] = 0;
    while( pFormatStr < pEnd )
    {
        pItem = new SubstItem();
        if ( !pItem )
        {
            ERR_NO_MEM( "new SubstItem()" );
            return -1;
        }
        
        if (  *pFormatStr == varChar )
        {
            if ( pFormatStr + 1 == pEnd )
            {
                HttpLog::parse_error( pCurLine ,  "Line ended with '$'" );
                err = 1;
            }
            if ( isdigit( *( pFormatStr + 1 ) ) )
            {
                pItem->setType( REF_RULE_SUBSTR );
                pItem->setIndex( *(pFormatStr + 1) - '0' );
                pFormatStr += 2;
            }
            else 
            {
                ++pFormatStr;
                if ( pItem->parseServerVar( pCurLine, pFormatStr, pEnd, isSSI ) )
                {
                    err = 1;
                }

            }
        }
        else
        {
            pItem->parseString( pFormatStr, pEnd, achVarChar );
        }
        if ( err )
        {
            delete pItem;
            return -1;
        }
        else
        {
            pLast->addNext( pItem );
            pLast = pItem;
        }
    }
    return 0;
}
Пример #3
0
AutoStr2 * SubstItem::setStr( const char * pStr, int len )
{
    m_value.m_pStr = new AutoStr2( pStr, len );
    if ( !m_value.m_pStr )
    {
        ERR_NO_MEM( "new AutoStr2()" );
    }

    return m_value.m_pStr;
}
Пример #4
0
int RewriteEngine::parseRules( char * &pRules, RewriteRuleList * pRuleList,
                        const RewriteMapList * pMapList )
{
    LinkedObj * pLast = pRuleList->tail();
    if ( !pLast )
        pLast = pRuleList->head();
    while( *pRules )
    {
        while( isspace( *pRules ) )
            ++pRules;
        if ( !*pRules )
            break;
        if ((( strncasecmp( pRules, "RewriteCond", 11 ) == 0 )&&
             ( isspace( *(pRules + 11)) ))||
            (( strncasecmp( pRules, "RewriteRule", 11 ) == 0 )&&
             ( isspace( *(pRules + 11)) )))
        {
            RewriteRule * pRule = new RewriteRule();
            if ( !pRule )
            {
                ERR_NO_MEM( "new RewriteRule()" );
                return -1;
            }
            int ret = pRule->parse( pRules, pMapList );
            if ( ret )
            {
                delete pRule;
                return 0;
            }
            pLast->addNext( pRule );
            pLast = pRule;
        }
        else
        {
            char * pLineEnd = strchr( pRules, '\n' );
            if ( pLineEnd )
                *pLineEnd = 0;
            if ( *pRules != '#' )
            {
                LOG_ERR(( "Invalid rewrite directive: %s", pRules ));
            }
            if ( pLineEnd )
                *pLineEnd = '\n';
            else
                break;
            pRules = pLineEnd + 1;
        }
    }
    return 0;
}
Пример #5
0
int HttpListener::addConnection( struct conn_data * pCur, int *iCount )
{
    int fd = pCur->fd;
    if ( checkAccess( pCur ))
    {
        no_timewait( fd );
        close( fd );
        --(*iCount);
        return 0;
    }
    HttpConnection* pConn = HttpConnPool::getConnection();
    if ( !pConn )
    {
        ERR_NO_MEM( "HttpConnPool::getConnection()" );
        close( fd );
        --(*iCount);
        return -1;
    }
    VHostMap * pMap;
    if ( m_pSubIpMap )
    {
        pMap = getSubMap( fd );
    }
    else
        pMap = getVHostMap();
    pConn->setVHostMap( pMap );
    pConn->setLogger( getLogger());
    pConn->setRemotePort( ntohs( ((sockaddr_in *)(pCur->achPeerAddr))->sin_port) );
    if ( pConn->setLink( pCur->fd, pCur->pInfo, pMap->getSSLContext() ) )
    {
        HttpConnPool::recycle( pConn );
        close( fd );
        --(*iCount);
        return -1;
    }
    fcntl( fd, F_SETFD, FD_CLOEXEC );
    fcntl( fd, F_SETFL, HttpGlobals::getMultiplexer()->getFLTag() );
    //pConn->tryRead();
    return 0;
}
Пример #6
0
int RewriteRule::parseCookieAction( const char *pCookie, const char * pEnd )
{
    if ( memchr( pCookie, ':', pEnd - pCookie ) == NULL )
    {
        HttpLog::parse_error( s_pCurLine,  "missing ':' in cookie string" );
        return -1;
    }
    RewriteSubstFormat* pFormat = new RewriteSubstFormat();
    if ( !pFormat )
    {
        ERR_NO_MEM( "new SubstFormat()" );
        return -1;
    }
    if ( pFormat->parse( pCookie, pEnd, NULL ) )
    {
        HttpLog::parse_error( s_pCurLine,  "failed to parse cookie string" );
        delete pFormat;
        return -1;
    }
    pFormat->setType( RewriteSubstFormat::COOKIE );
    m_env.append( pFormat );
    
    return 0;
}
Пример #7
0
int RewriteRule::parseOneFlag( const char *&pRuleStr, const char * pEnd )
{
    switch( *pRuleStr )
    {
    case 'B':
    case 'b':
        m_flag |= RULE_FLAG_BR_ESCAPE;
        ++pRuleStr;
        break;
    case 'C':
    case 'c':
        if ( (*(pRuleStr+1) | 0x20) == 'o' )
        {
            pRuleStr += 2;
            if ( strncasecmp( pRuleStr, "okie", 4 ) == 0 )
                pRuleStr += 4;
            if ( *pRuleStr == '=' )
            {
                ++pRuleStr;
                size_t n = strcspn( pRuleStr, ",] \t\r\n" );
                if ( n > 0 )
                {
                    const char * pCookie = pRuleStr;
                    pRuleStr += n;
                    return parseCookieAction( pCookie, pRuleStr );
                }
                else
                {
                    HttpLog::parse_error( s_pCurLine,  "invalid cookie action string" );
                    return -1;
                }
            }
            break;
        }
        m_flag |= RULE_FLAG_CHAIN;
        if ( strncasecmp( pRuleStr, "chain", 5 ) == 0 )
            pRuleStr += 5;
        else
            ++pRuleStr;
        break;
    case 'D':
    case 'd':
        if ( strncasecmp( pRuleStr, "DPI", 3 ) == 0 )
        {
            pRuleStr += 3;
            m_flag |= RULE_FLAG_DPI;
        }
        else
        if ( strncasecmp( pRuleStr, "discardpathinfo", 15 ) == 0 )
        {
            pRuleStr += 15;
            m_flag |= RULE_FLAG_DPI;
        }
        else
            ++pRuleStr;
        break;
    case 'E':
    case 'e':
        if ( strncasecmp( pRuleStr, "end", 3 ) == 0 )
        {
            pRuleStr += 3;
            m_flag |= RULE_FLAG_END;
            m_flag |= RULE_FLAG_LAST;
            break;
        }
        if ( strncasecmp( pRuleStr, "env", 3 ) == 0 )
            pRuleStr += 3;
        else
            ++pRuleStr;
        if ( *pRuleStr == '=' )
        {
            ++pRuleStr;
            size_t n = strcspn( pRuleStr, ",] \t\r\n" );
            if ( n > 0 )
            {
                const char * pEnv = pRuleStr;
                pRuleStr += n;
                if ( memchr( pEnv, ':', n ) == NULL )
                {
                    HttpLog::parse_error( s_pCurLine,  "missing ':' in env string" );
                    return -1;
                }
                RewriteSubstFormat* pFormat = new RewriteSubstFormat();
                if ( !pFormat )
                {
                    ERR_NO_MEM( "new SubstFormat()" );
                    return -1;
                }
                if ( pFormat->parse( pEnv, pRuleStr, NULL ) )
                {
                    HttpLog::parse_error( s_pCurLine,  "failed to parse env string" );
                    delete pFormat;
                    return -1;
                }
                pFormat->setType( RewriteSubstFormat::ENV );
                m_env.append( pFormat );
            }
            else
            {
                HttpLog::parse_error( s_pCurLine,  "invalid env string, empty string" );
                return -1;
            }
        }
        break;        
    case 'F':
    case 'f':
        m_action = RULE_ACTION_FORBID;
        m_flag |= RULE_FLAG_LAST;
        m_statusCode = SC_403;
        if ( strncasecmp( pRuleStr, "forbidden", 9 ) == 0 )
            pRuleStr += 9;
        else
            ++pRuleStr;
        break;
    case 'G':
    case 'g':
        m_action = RULE_ACTION_GONE;
        m_flag |= RULE_FLAG_LAST;
        m_statusCode = SC_410;
        if ( strncasecmp( pRuleStr, "gone", 4 ) == 0 )
            pRuleStr += 4;
        else
            ++pRuleStr;
        break;
    case 'L':
    case 'l':
        m_flag |= RULE_FLAG_LAST;
        if ( strncasecmp( pRuleStr, "last", 4 ) == 0 )
        {
            pRuleStr += 4;
        }
        else    // 'L'
            ++pRuleStr;
        break;
    case 'n':
    case 'N':
        if ( strncasecmp( pRuleStr, "nocase", 6 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOCASE;
            pRuleStr += 6;
        }
        else if ( strncasecmp( pRuleStr, "nc", 2 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOCASE;
            pRuleStr += 2;
        }
        else if ( strncasecmp( pRuleStr, "nosubreq", 8 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOSUBREQ;
            pRuleStr += 8;
        }
        else if ( strncasecmp( pRuleStr, "ns", 2 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOSUBREQ;
            pRuleStr += 2;
        }
        else if ( strncasecmp( pRuleStr, "noescape", 8 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOESCAPE;
            pRuleStr += 8;
        }
        else if ( strncasecmp( pRuleStr, "ne", 2 ) == 0 )
        {
            m_flag |= RULE_FLAG_NOESCAPE;
            pRuleStr += 2;
        }
        else if ( strncasecmp( pRuleStr, "next", 4 ) == 0 )
        {
            m_flag |= RULE_FLAG_NEXT;
            pRuleStr += 4;
        }
        else    // 'N'
        {
            m_flag |= RULE_FLAG_NEXT;
            ++pRuleStr;
        }
        break;
    case 'P':
    case 'p':
        if ( strncasecmp( pRuleStr, "passthrough", 11 ) == 0 )
        {
            m_flag |= RULE_FLAG_PASSTHRU;
            pRuleStr += 11;
        }
        else if ( strncasecmp( pRuleStr, "pt", 2 ) == 0 )
        {
            m_flag |= (RULE_FLAG_PASSTHRU | RULE_FLAG_LAST);
            pRuleStr += 2;
        }
        else
        {
            m_action = RULE_ACTION_PROXY;
            m_flag |= RULE_FLAG_LAST;
            m_statusCode = -2; //proxy
            if ( strncasecmp( pRuleStr, "proxy", 5 ) == 0 )
            {
                pRuleStr += 5;
            }
            else    // 'P'
            {
                ++pRuleStr;
            }
        }
        break;

    case 'Q':
    case 'q':
        if ( strncasecmp( pRuleStr, "qsappend", 8 ) == 0 )
        {
            m_flag |= RULE_FLAG_QSAPPEND;
            pRuleStr += 8;
        }
        else if ( strncasecmp( pRuleStr, "qsa", 3 ) == 0 )
        {
            m_flag |= RULE_FLAG_QSAPPEND;
            pRuleStr += 3;
        }
        else if ( strncasecmp( pRuleStr, "qsdiscard", 8 ) == 0 )
        {
            m_flag |= RULE_FLAG_QSDISCARD;
            pRuleStr += 8;
        }
        else if ( strncasecmp( pRuleStr, "qsd", 3 ) == 0 )
        {
            m_flag |= RULE_FLAG_QSDISCARD;
            pRuleStr += 3;
        }
        else
        {
            HttpLog::parse_error( s_pCurLine,  "Unknown rewrite rule flag" );
            return -1;
        }
        break;
    case 'R':
    case 'r':
        m_action = RULE_ACTION_REDIRECT;
        if ( strncasecmp( pRuleStr, "redirect", 8 ) == 0 )
        {
            pRuleStr += 8;
        }
        else
        {
            ++pRuleStr;
        }
        if ( *pRuleStr == '=' )
        {
            ++pRuleStr;
            size_t n = strcspn( pRuleStr, ",] \t\r\n" );
            if ( n == 0 )
            {
                m_statusCode = SC_302;
            }
            else if (( strncasecmp( pRuleStr, "temp", 4 ) == 0 )&&( n == 4 ))
            {
                pRuleStr += 4;
                m_statusCode = SC_302;
            }
            else if (( strncasecmp( pRuleStr, "permanent", 9 ) == 0 )&&( n == 9 ))
            {
                pRuleStr += 9;
                m_statusCode = SC_301;
            }
            else if (( strncasecmp( pRuleStr, "seeother", 8 ) == 0 )&&( n == 8 ))
            {
                pRuleStr += 8;
                m_statusCode = SC_303;
            }
            else 
            {
                m_statusCode = HttpStatusCode::codeToIndex( pRuleStr );
                if ( m_statusCode == -1 )
                    m_statusCode = SC_302;
                else
                    pRuleStr += n;
            }
        }
        else
        {
            m_statusCode = SC_302;
        }
        break;    
    case 'S':
    case 's':
        if ( strncasecmp( pRuleStr, "skip", 4 ) == 0 )
        {
            pRuleStr += 4;
        }
        else
            ++pRuleStr;
        if ( *pRuleStr == '=' )
        {
            ++pRuleStr;
            char * p;
            m_skipRules = strtol( pRuleStr, &p, 10 );
            if ( p == pRuleStr )
            {
                HttpLog::parse_error( s_pCurLine,  "invalid number in 'skip' flag" );
                return -1;
            }
            pRuleStr = p;
        }
        else
        {
            HttpLog::parse_error( s_pCurLine,  "invalid 'skip' flag, '=' expected" );
            return -1;
        }
        break;
    case 'T':
    case 't':
    case 'H':
    case 'h':
        if ( strncasecmp( pRuleStr, "type", 4 ) == 0 )
        {
            pRuleStr += 4;
        }
        else if ( strncasecmp( pRuleStr, "handler", 7 ) == 0 )
            pRuleStr += 7;
        else
            ++pRuleStr;
        if ( *pRuleStr == '=' )
        {
            ++pRuleStr;
            size_t n = strcspn( pRuleStr, ",] \t\r\n" );
            if ( n == 0 )
            {
                HttpLog::parse_error( s_pCurLine,  "invalid 'type' flag, missing mime type." );
                return -1;
            }
            m_sMimeType.setStr( pRuleStr, n );
            pRuleStr += n;
        }
        else
        {
            HttpLog::parse_error( s_pCurLine,  "invalid 'type' flag, '=' expected" );
            return -1;
        }
        break;
    default:
        HttpLog::parse_error( s_pCurLine,  "Unknown rewrite rule flag" );
        return -1;
        break;
    }
    return 0;
}
Пример #8
0
int RewriteSubstFormat::parse( const char * pFormatStr, const char * pEnd, const RewriteMapList * pMaps )
{
    while(( pFormatStr < pEnd )&&( isspace( *pFormatStr )))
        ++pFormatStr;
    int err = 0;
    LinkedObj * pLast = head();
    RewriteSubstItem * pItem;
    while( pFormatStr < pEnd )
    {
        pItem = new RewriteSubstItem();
        if ( !pItem )
        {
            ERR_NO_MEM( "new SubstItem()" );
            return -1;
        }
        
        switch( *pFormatStr )
        {
        case '$':
            if ( pFormatStr + 1 == pEnd )
            {
                HttpLog::parse_error( s_pCurLine,  "Line ended with '$'" );
                err = 1;
                break;
            }
            if ( *( pFormatStr + 1 ) == '{' )
            {
                if ( !pMaps )
                {
                    HttpLog::parse_error( s_pCurLine,  "No rewrite map defined" );
                    err = 1;
                    break;
                }
                pItem->setType( REF_MAP );
                MapRefItem * pMapRef = new MapRefItem();
                if ( !pMapRef )
                {
                    ERR_NO_MEM( "new MapRefItem()" );
                    err = 1;
                    break;
                }
                if ( pMapRef->parse( pFormatStr, pEnd, pMaps ) )
                {
                    delete pMapRef;
                    err = 1;
                    break;
                }
                pItem->setMapRef( pMapRef );
            }
            else if ( isdigit( *( pFormatStr + 1 ) ) )
            {
                pItem->setType( REF_RULE_SUBSTR );
                pItem->setIndex( *(pFormatStr + 1) - '0' );
                pFormatStr += 2;
            }
            else
            {
                HttpLog::parse_error( s_pCurLine,  "'$' should be followed by a digit for a RewriteRule backreference." );
                pItem->setType( REF_STRING );
                pItem->setStr( pFormatStr, 1 );
                ++pFormatStr;
            }
            break;
        case '%':
            if ( pFormatStr + 1 == pEnd )
            {
                HttpLog::parse_error( s_pCurLine,  "Line ended with '%'" );
                err = 1;
                break;
            }
            if ( *( pFormatStr + 1 ) == '{' )
            {
                ++pFormatStr;
                if ( pItem->parseServerVar( s_pCurLine, pFormatStr, pEnd ) )
                {
                    err = 1;
                    break;
                }
            }
            else if ( isdigit( *( pFormatStr + 1 ) ) )
            {
                pItem->setType( REF_COND_SUBSTR );
                pItem->setIndex( *(pFormatStr + 1) - '0' );
                pFormatStr += 2;
            }
            else
            {
                HttpLog::parse_error( s_pCurLine,  "'%' should be followed by a digit for a RewriteCond backreference." );
                pItem->setType( REF_STRING );
                pItem->setStr( pFormatStr, 1 );
                ++pFormatStr;
            }
            break;
        case '\\':
        default:
            pItem->parseString( pFormatStr, pEnd, "$%" );
            break;
        }
        if ( err )
        {
            delete pItem;
            return -1;
        }
        else
        {
            pLast->addNext( pItem );
            pLast = pItem;
        }
    }
    return 0;
}
Пример #9
0
int RewriteRule::parse( char * &pRule, const RewriteMapList * pMaps )
{
    char * pCur;
    char * pLineEnd;
    LinkedObj * pLast = m_conds.head();
    assert( pLast->next() == NULL );
    while( *pRule )
    {
        while( isspace( *pRule ) )
            ++pRule;
        if ( !*pRule )
            break;
        pCur = pRule;
        pLineEnd = strchr( pCur, '\n' );
        if ( !pLineEnd )
        {
            pLineEnd = pCur + strlen( pCur );
            pRule = pLineEnd;
        }
        else
        {
            pRule = pLineEnd + 1;
            *pLineEnd = 0;
        }
        s_pCurLine = pCur;
        if ( *pCur != '#' )
        {
            if (( strncasecmp( pCur, "RewriteCond", 11 ) == 0 )&&
                ( isspace( *(pCur + 11)) ))
            {
                RewriteCond * pCond = new RewriteCond();
                if ( !pCond )
                {
                    ERR_NO_MEM( "new RewriteCond()" );
                    return -1;
                }
                
                if ( pCond->parse( pCur+12, pLineEnd, pMaps ) )
                {
                    delete pCond;
                    HttpLog::parse_error( s_pCurLine,  "invalid rewrite condition" );
                    return -1;
                }
                pLast->addNext( pCond );
                pLast = pCond;
            }
            else if (( strncasecmp( pCur, "RewriteRule", 11 ) == 0 )&&
                     ( isspace( *(pCur + 11)) ))
            {
                int ret = parseRule( pCur+12, pLineEnd, pMaps );
                pCur = pLineEnd+1;
                return ret;
            }
            else
            {
                HttpLog::parse_error( s_pCurLine,  "invalid rewrite directive " );
                return -1;
            }
        }
    }

    return -1;
}
Пример #10
0
int HttpListener::batchAddConn( struct conn_data * pBegin,
                            struct conn_data *pEnd, int *iCount )
{
    struct conn_data * pCur = pBegin;
    int n = pEnd - pBegin;
    while( pCur < pEnd )
    {
        if ( checkAccess( pCur))
        {
            no_timewait( pCur->fd );
            close( pCur->fd );
            pCur->fd = -1;
            --(*iCount);
            --n;
        }
        ++pCur;
    }
    if ( n <= 0 )
        return 0;
    HttpConnection* pConns[CONN_BATCH_SIZE];
    int ret = HttpConnPool::getConnections( pConns, n);
    pCur = pBegin;
    if ( ret <= 0 )
    {
        ERR_NO_MEM( "HttpConnPool::getConnections()" );
        LOG_ERR(( "need %d connections, allocated %d connections!", n, ret ));
        while( pCur < pEnd )
        {
            if ( pCur->fd != -1 )
            {
                close( pCur->fd );
                --(*iCount);
            }
            ++pCur;
        }
        return -1;
    }
    HttpConnection** pConnEnd = &pConns[ret];
    HttpConnection** pConnCur = pConns;
    VHostMap * pMap;
    int flag = HttpGlobals::getMultiplexer()->getFLTag();
    while( pCur < pEnd )
    {
        register int fd = pCur->fd;
        if ( fd != -1 )
        {
            assert( pConnCur < pConnEnd );
            HttpConnection * pConn = *pConnCur;

            if ( m_pSubIpMap )
            {
                pMap = getSubMap( fd );
            }
            else
                pMap = getVHostMap();

            pConn->setVHostMap( pMap );
            pConn->setLogger( getLogger());
            pConn->setRemotePort( ntohs( ((sockaddr_in *)(pCur->achPeerAddr))->sin_port) );

        //    if ( getDedicated() )
        //    {
        //        //pConn->accessGranted();
        //    }
            if ( !pConn->setLink( fd, pCur->pInfo, pMap->getSSLContext() ) )
            {
                fcntl( fd, F_SETFD, FD_CLOEXEC );
                fcntl( fd, F_SETFL, flag );
                ++pConnCur;
                //pConn->tryRead();
            }
            else
            {
                close( fd );
                --(*iCount);
            }
        }
        ++pCur;
    }
    if ( pConnCur < pConnEnd )
    {
        HttpConnPool::recycle( pConnCur, pConnEnd - pConnCur);
    }

    return 0;
}
Пример #11
0
/*
 *  int pmapFilterSetupBitmap(uint32_t **bitmap, uint32_t **bitmap_size,
 *                            skPrefixMap_t *prefix_map,
 *                            char *opt_arg, char *pmap_path);
 *
 *    Parses 'opt_arg', a string representation of comma-separated
 *    pmap values to filter on with respect to the given 'prefix_map',
 *    and sets the relevant bits in the bit-vector 'bitmap', whose
 *    current size is 'bitmap_size'.  Creates the bitmap if necessary
 *    and may adjust the bitmap's size.  Returns -1 if the argument
 *    was not parsable or if there is a memory allocation error.
 */
static int
pmapFilterSetupBitmap(
    uint32_t              **bitmap_arg,
    uint32_t               *bitmap_size,
    const skPrefixMap_t    *prefix_map,
    const char             *opt_arg,
    const char             *pmap_path)
{
    uint32_t bmap_len;
    char *arg_copy = NULL;
    char *label;
    char *next_token;
    uint32_t code;
    uint32_t *bitmap = NULL;
    int rv = -1;

    if (ignore_prefix_map) {
        return 0;
    }

    assert(bitmap_arg);
    assert(prefix_map);
    assert(opt_arg);

    /* Get a pointer to the bitmap---creating it if required */
    if (*bitmap_arg) {
        bitmap = *bitmap_arg;
    } else {
        /* Allocate the bitmap. */
        bmap_len = skPrefixMapDictionaryGetWordCount(prefix_map);

        bitmap = (uint32_t*)calloc(PMAP_BMAP_SIZE(bmap_len), sizeof(uint32_t));
        if (NULL == bitmap) {
            ERR_NO_MEM(bitmap);
            goto END;
        }
        *bitmap_size = bmap_len;
    }

    /* Make a modifiable copy of the user's argument */
    arg_copy = strdup(opt_arg);
    if (arg_copy == NULL) {
        ERR_NO_MEM(arg_copy);
        goto END;
    }

    /* Find each token which should be a label in the pmap */
    next_token = arg_copy;
    while ((label = strsep(&next_token, ",")) != NULL) {
        code = skPrefixMapDictionaryLookup(prefix_map, label);
        if (SKPREFIXMAP_NOT_FOUND == code) {
            /* label was not found in dictionary.  if label is a
             * number and if any key in the prefix map has that number
             * as its value, set that position in the bitmap,
             * reallocating the bitmap if necessary */
            if (skStringParseUint32(&code, label, 0, SKPREFIXMAP_MAX_VALUE)) {
                skAppPrintErr(("The label '%s' was not found in prefix map\n"
                               "\tdictionary loaded from '%s'"),
                              label, pmap_path);
                goto END;
            }

            if (0 == pmapCheckValueIsValid(prefix_map, code)) {
                skAppPrintErr(("The value '%s' was not found in prefix map\n"
                               "\tdictionary loaded from '%s'"),
                              label, pmap_path);
                goto END;
            }

            /* ensure bitmap can set the bit 'code' */
            bmap_len = code + 1;

            /* see if we need to grow the bitmap */
            if (PMAP_BMAP_SIZE(bmap_len) > PMAP_BMAP_SIZE(*bitmap_size)) {
                uint32_t *old = bitmap;
                bitmap = (uint32_t*)realloc(bitmap, (PMAP_BMAP_SIZE(bmap_len)
                                                     * sizeof(uint32_t)));
                if (NULL == bitmap) {
                    bitmap = old;
                    ERR_NO_MEM(bitmap);
                    goto END;
                }
                memset(&bitmap[PMAP_BMAP_SIZE(*bitmap_size)], 0,
                       ((PMAP_BMAP_SIZE(bmap_len)-PMAP_BMAP_SIZE(*bitmap_size))
                        * sizeof(uint32_t)));
            }
            /* alway set bitmap size to maximum number */
            if (bmap_len > *bitmap_size) {
                *bitmap_size = bmap_len;
            }
        }
        PMAP_BMAP_SET(bitmap, code);
    }

    /* Success */
    rv = 0;
    *bitmap_arg = bitmap;

  END:
    if (*bitmap_arg == NULL && bitmap != NULL) {
        free(bitmap);
    }
    if (arg_copy) {
        free(arg_copy);
    }
    return rv;
}
Пример #12
0
/*
 *  skplugin_err_t pmapfile_handler(const char *opt_arg, void *cbdata)
 *
 *    Handler for --pmap-file option.  Actually registers the filter and
 *    fields.
 */
static skplugin_err_t
pmapfile_handler(
    const char         *opt_arg,
    void        UNUSED(*cbdata))
{
    /* Whether we have seen any unnamed pmaps */
    static int           have_unnamed_pmap = 0;
    skPrefixMapErr_t     map_error         = SKPREFIXMAP_OK;
    skstream_t          *stream            = NULL;
    skPrefixMap_t       *prefix_map        = NULL;
    pmap_data_t         *pmap_data         = NULL;
    int                  ok;
    const char          *filename;
    const char          *sep;
    const char          *mapname;
    char                *prefixed_name     = NULL;
    char                *short_prefixed_name;
    size_t               namelen           = 0;
    size_t               i;
    int                  rv                = SKPLUGIN_ERR;
    skplugin_callbacks_t regdata;

    /* We can only have one pmap whenever we any any pmap without a
     * mapname.  If we've seen one and enter this function a second
     * time, it is an error */
    if (have_unnamed_pmap) {
        skAppPrintErr(("Invalid %s: You may use only one prefix map"
                       " when you are\n"
                       "\tusing a prefix map without specifying a mapname"),
                      pmap_file_option);
        return SKPLUGIN_ERR;
    }

    /* Parse the argument into a field name and file name */
    sep = strchr(opt_arg, ':');
    if (NULL == sep) {
        /* We do not have a mapname.  We'll check for one in the pmap
         * once we read it. */
        mapname = NULL;
        filename = opt_arg;
    } else {
        /* A mapname was supplied on the command line */
        if (sep == opt_arg) {
            skAppPrintErr("Invalid %s: Zero length mapnames are not allowed",
                          pmap_file_option);
            return SKPLUGIN_ERR;
        }
        if (memchr(opt_arg, ',', sep - opt_arg) != NULL) {
            skAppPrintErr("Invalid %s: The mapname may not include a comma",
                          pmap_file_option);
            return SKPLUGIN_ERR;
        }
        mapname = opt_arg;
        filename = sep + 1;
        namelen = sep - opt_arg;
    }

    ok = skpinOpenDataInputStream(&stream, SK_CONTENT_SILK, filename);
    if (ok == -1) {
        /* problem opening file */
        skAppPrintErr("Failed to open the prefix map file '%s'",
                      filename);
        return SKPLUGIN_ERR;
    }
    if (ok == 1) {
        /* master needs to process the file, since it may contain the
         * map name we use for creating switches */
        if ((rv = skStreamCreate(&stream, SK_IO_READ, SK_CONTENT_SILK))
            || (rv = skStreamBind(stream, filename))
            || (rv = skStreamOpen(stream)))
        {
            skStreamPrintLastErr(stream, rv, &skAppPrintErr);
            skStreamDestroy(&stream);
            return SKPLUGIN_ERR;
        }

        /* the master can ignore the file for filtering */
        ignore_prefix_map = 1;
    }

    map_error = skPrefixMapRead(&prefix_map, stream);
    if (SKPREFIXMAP_OK != map_error) {
        if (SKPREFIXMAP_ERR_IO == map_error) {
            skStreamPrintLastErr(stream, skStreamGetLastReturnValue(stream),
                                 &skAppPrintErr);
        } else {
            skAppPrintErr("Failed to read the prefix map file '%s': %s",
                          opt_arg, skPrefixMapStrerror(map_error));
        }
        skStreamDestroy(&stream);
        return SKPLUGIN_ERR;
    }
    skStreamDestroy(&stream);

    if (NULL == mapname) {
        /* No mapname was supplied on the command line.  Check for a
         * mapname insided the pmap. */
        mapname = skPrefixMapGetMapName(prefix_map);
        if (mapname) {
            /* The pmap supplied a mapname */
            namelen = strlen(mapname);
        } else {
            /* No mapname.  Accept for legacy purposes, unless we have
             * read any other pmaps */
            have_unnamed_pmap = 1;
            if (skVectorGetCount(pmap_vector) != 0) {
                skAppPrintErr(("Invalid %s: You may use only one prefix map"
                               " when you are\n"
                               "\t using a prefix map without"
                               " specifying a mapname"),
                              pmap_file_option);
                goto END;
            }
        }
    }

    /* Allocate the pmap_data structure */
    pmap_data = (pmap_data_t *)calloc(1, sizeof(*pmap_data));
    if (pmap_data == NULL) {
        ERR_NO_MEM(pmap_data);
        rv = SKPLUGIN_ERR_FATAL;
        goto END;
    }

    /* pmap_data now "owns" prefix_map */
    pmap_data->pmap = prefix_map;
    prefix_map = NULL;

    /* Cache the content type */
    pmap_data->type = skPrefixMapGetContentType(pmap_data->pmap);

    /* Fill the direction structure for each direction */
    pmap_data->sdir.dir = DIR_SOURCE;
    pmap_data->ddir.dir = DIR_DEST;
    pmap_data->adir.dir = DIR_ANY;
    pmap_data->sdir.data = pmap_data;
    pmap_data->ddir.data = pmap_data;
    pmap_data->adir.data = pmap_data;

    /* Record the path to the pmap file */
    pmap_data->filepath = strdup(filename);
    if (NULL == pmap_data->filepath) {
        ERR_NO_MEM(pmap_data->filepath);
        rv = SKPLUGIN_ERR_FATAL;
        goto END;
    }

    if (mapname == NULL)  {
        /* Pmap without a mapname. */

        /* Add the proper legacy option names to the pmap_data structure */
        switch (pmap_data->type) {
          case SKPREFIXMAP_CONT_ADDR_V4:
          case SKPREFIXMAP_CONT_ADDR_V6:
            pmap_data->sdir.filter_option = strdup(pmap_saddress_option);
            pmap_data->ddir.filter_option = strdup(pmap_daddress_option);
            pmap_data->adir.filter_option = strdup(pmap_aaddress_option);
            break;
          case SKPREFIXMAP_CONT_PROTO_PORT:
            pmap_data->sdir.filter_option = strdup(pmap_sport_proto_option);
            pmap_data->ddir.filter_option = strdup(pmap_dport_proto_option);
            pmap_data->adir.filter_option = strdup(pmap_aport_proto_option);
            break;
        }
        if ((pmap_data->sdir.filter_option == NULL)
            || (pmap_data->ddir.filter_option == NULL)
            || (pmap_data->adir.filter_option == NULL))
        {
            ERR_NO_MEM(filter_option);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }
        pmap_data->mapname = strdup(pmap_title_val);
        pmap_data->sdir.field_name = strdup(pmap_title_sval);
        pmap_data->ddir.field_name = strdup(pmap_title_dval);
        if ((pmap_data->mapname == NULL)
            || (pmap_data->sdir.field_name == NULL)
            || (pmap_data->ddir.field_name == NULL))
        {
            ERR_NO_MEM(field_name);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }

    } else { /* if (mapname == NULL) */

        /* Create the field names*/
        pmap_data->mapname = (char*)malloc(namelen + 1);
        if (NULL == pmap_data->mapname) {
            ERR_NO_MEM(pmap_data->mapname);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }
        strncpy(pmap_data->mapname, mapname, namelen);
        pmap_data->mapname[namelen] = '\0';

        /* Allocate space for the [pmap-]{src-,dst-}<mapname> string */
        prefixed_name
            = (char*)malloc(namelen + pmap_prefix_len + dir_name_len + 1);
        if (NULL == prefixed_name) {
            ERR_NO_MEM(prefixed_name);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }

        /* Copy in the pmap- prefix */
        strncpy(prefixed_name, pmap_prefix, pmap_prefix_len);

        /* short name (for fields) starts at the {src-,dst-} */
        short_prefixed_name = prefixed_name + pmap_prefix_len;

        /* add in the actual field name, and zero terminate it */
        strncpy(short_prefixed_name + dir_name_len, mapname, namelen);
        short_prefixed_name[namelen + dir_name_len] = '\0';

        /* Create the destination-themed names */
        strncpy(short_prefixed_name, src_dir_name, dir_name_len);
        pmap_data->sdir.filter_option = strdup(prefixed_name);
        pmap_data->sdir.field_name = strdup(short_prefixed_name);
        if ((pmap_data->sdir.filter_option == NULL)
            || (pmap_data->sdir.field_name == NULL))
        {
            ERR_NO_MEM(pmap_data->sdir);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }
        strncpy(short_prefixed_name, dst_dir_name, dir_name_len);
        pmap_data->ddir.filter_option = strdup(prefixed_name);
        pmap_data->ddir.field_name = strdup(short_prefixed_name);
        if ((pmap_data->ddir.filter_option == NULL)
            || (pmap_data->ddir.field_name == NULL))
        {
            ERR_NO_MEM(pmap_data->ddir);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }
        strncpy(short_prefixed_name, any_dir_name, dir_name_len);
        pmap_data->adir.filter_option = strdup(prefixed_name);
        if (pmap_data->adir.filter_option == NULL) {
            ERR_NO_MEM(pmap_data->adir);
            rv = SKPLUGIN_ERR_FATAL;
            goto END;
        }

        /* Free the temporary name buffer */
        free(prefixed_name);
        prefixed_name = NULL;

    } /* if (mapname == NULL) */


    /* Verify unique field names */
    for (i = 0; i < skVectorGetCount(pmap_vector); i++) {
        pmap_data_t *p;

        skVectorGetValue(&p, pmap_vector, i);
        if ((strcmp(pmap_data->mapname, p->mapname) == 0) ||
            (strcmp(pmap_data->sdir.field_name, p->sdir.field_name) == 0) ||
            (strcmp(pmap_data->ddir.field_name, p->ddir.field_name) == 0))
        {
            skAppPrintErr(("Invalid %s: Multiple pmaps use the mapname '%s':\n"
                           "\t%s\n\t%s"),
                          pmap_file_option, pmap_data->mapname,
                          p->filepath, pmap_data->filepath);
            rv = SKPLUGIN_ERR;
            goto END;
        }
    }

    /* Register fields and filter options */
    memset(&regdata, 0, sizeof(regdata));
    regdata.init = pmap_field_init;
    regdata.column_width = 0;
    regdata.bin_bytes = 4;
    regdata.rec_to_text = pmap_text_fn;
    regdata.rec_to_bin = pmap_bin_fn;
    regdata.bin_to_text = pmap_bin_to_text_fn;

    for (i = 0; i < 2; ++i) {
        directed_pmap_data_t *dir = ((0 == i)
                                     ? &pmap_data->sdir
                                     : &pmap_data->ddir);

        skpinRegField(&dir->field, dir->field_name, NULL, &regdata, dir);
        skpinRegOption2(dir->filter_option,
                        REQUIRED_ARG,
                        NULL, &pmap_filter_help,
                        &pmap_handle_filter_option, dir,
                        1, SKPLUGIN_FN_FILTER);
    }

    /* Register the "any" filter separately */
    skpinRegOption2(pmap_data->adir.filter_option,
                    REQUIRED_ARG,
                    NULL, &pmap_filter_help,
                    &pmap_handle_filter_option, &pmap_data->adir,
                    1, SKPLUGIN_FN_FILTER);


    if (skVectorAppendValue(pmap_vector, &pmap_data)) {
        rv = SKPLUGIN_ERR_FATAL;
        goto END;
    }

    rv = SKPLUGIN_OK;

  END:
    /* Free the temporary name buffer */
    if (prefixed_name) {
        free(prefixed_name);
    }
    if (rv != SKPLUGIN_OK) {
        if (prefix_map) {
            skPrefixMapDelete(prefix_map);
        }
        if (pmap_data) {
            pmap_data_destroy(pmap_data);
        }
    }
    return (skplugin_err_t)rv;
}
Пример #13
0
/* Public entry point */
skplugin_err_t
skPrefixMapAddFields(
    uint16_t            major_version,
    uint16_t            minor_version,
    void        UNUSED(*data))
{
    skplugin_err_t err;

#define PMAP_FILE_HELP(str_arg)                                         \
    ("Prefix map file to read.  Def. None.  When the argument has\n"    \
     "\tthe form \"<mapfile>:<filename>\","                             \
     " the \"mapname\" is used to generate\n"                           \
     str_arg)

    assert(strlen(src_dir_name) == strlen(dst_dir_name));

    /* Check API version */
    err = skpinSimpleCheckVersion(major_version, minor_version,
                                  PLUGIN_API_VERSION_MAJOR,
                                  PLUGIN_API_VERSION_MINOR,
                                  skAppPrintErr);
    if (err != SKPLUGIN_OK) {
        return err;
    }

    /* Initialize global variables */
    pmap_vector = skVectorNew(sizeof(pmap_data_t *));
    if (pmap_vector == NULL) {
        ERR_NO_MEM(pmap_vector);
        return SKPLUGIN_ERR;
    }

    /* Add --pmap-file to apps that accept RWREC: rwcut, rwsort, etc */
    err = skpinRegOption2(pmap_file_option,
                          REQUIRED_ARG,
                          PMAP_FILE_HELP(
                              "\tfield names.  As such, this switch must"
                              " precede the --fields switch."), NULL,
                          pmapfile_handler, NULL,
                          2,
                          SKPLUGIN_FN_REC_TO_TEXT,
                          SKPLUGIN_FN_REC_TO_BIN);
    if (err == SKPLUGIN_ERR_FATAL) {
        return err;
    }

    /* Add --pmap-column-width to apps that produce TEXT: rwcut, rwuniq  */
    err = skpinRegOption2(pmap_column_width_option,
                          REQUIRED_ARG,
                          "Maximum column width to use for output.", NULL,
                          pmap_column_width_handler, NULL,
                          2,
                          SKPLUGIN_FN_REC_TO_TEXT,
                          SKPLUGIN_FN_BIN_TO_TEXT);
    if (err == SKPLUGIN_ERR_FATAL) {
        return err;
    }

    /* Add --pmap-file to rwfilter */
    err = skpinRegOption2(pmap_file_option,
                          REQUIRED_ARG,
                          PMAP_FILE_HELP(
                              "\tfiltering switches.  This switch must"
                              " precede other --pmap-* switches."), NULL,
                          pmapfile_handler, NULL,
                          1, SKPLUGIN_FN_FILTER);
    if (err == SKPLUGIN_ERR_FATAL) {
        return err;
    }

    /* Register cleanup function */
    skpinRegCleanup(pmap_teardown);

    return SKPLUGIN_OK;
}