Example #1
0
/*
 * Arguments:
 *      pat             Pointer to memory that will be set to point to an
 *                      allocated Pattern.  Set on and only on success.
 *      ere             The extended regular expression.  Caller may free upon
 *                      return.  If the expression is a pathological 
 *                      regular-expression, then it will be repaired.
 *      ignoreCase      Whether or not to ignore case in matches.
 *
 * Returns:
 *      NULL    Success.  *pat is set.
 *      else    Error object.  err_code() values:
 *                      1       System error.  *pat not set.
 *                      2       Invalid ERE.  *pat not set.
 */
ErrorObj*
pat_new(
    Pattern** const             pat,
    const char* const           ere,
    const int                   ignoreCase)
{
    ErrorObj*   errObj = NULL;  /* success */
    int         isTrivial = 0 == strcmp(".*", ere);

    if (isTrivial && NULL != matchAll) {
        *pat = matchAll;
    }
    else {
        Pattern* const  ptr = (Pattern*)malloc(sizeof(Pattern));

        if (NULL == ptr) {
            errObj = ERR_NEW2(1, NULL, "Couldn't allocate %lu bytes: %s",
                (unsigned long)sizeof(Pattern), strerror(errno));
        }
        else {
            ptr->string = strdup(ere);

            if (NULL == ptr->string) {
                errObj = ERR_NEW2(1, NULL, "Couldn't copy string \"%s\": %s",
                    ere, strerror(errno));
            }
            else {
                int     err;

                (void)re_vetSpec(ptr->string);

                if (err = regcomp(&ptr->reg, ptr->string,
                    REG_EXTENDED | REG_NOSUB | (ignoreCase ? REG_ICASE : 0))) {

                    char        buf[512];

                    (void)regerror(err, &ptr->reg, buf, sizeof(buf));

                    errObj = ERR_NEW2((REG_ESPACE == err) ? 1 : 2, NULL,
                        "Couldn't compile ERE \"%s\": %s", ptr->string, buf);
                }
                else {
                    ptr->ignoreCase = ignoreCase;
                    *pat = ptr;

                    if (isTrivial && NULL == matchAll)
                        matchAll = ptr;
                }                       /* ERE compiled */

                if (errObj)
                    free(ptr->string);
            }                           /* ptr->string allocated */

            if (errObj)
                free(ptr);
        }                               /* "ptr" allocated */
    }                                   /* non-trivial ERE or matchAll==NULL */

    return errObj;
}
Example #2
0
/*
 * Returns a new upstream filter.
 *
 * Arguments:
 *      upFilter        Pointer to pointer to returned upstream filter.  Must
 *                      not be NULL.  Set on and only on success.
 * Returns:
 *      NULL            Success.
 *      else            Failure error object.
 */
ErrorObj*
upFilter_new(
    UpFilter** const    upFilter)
{
    ErrorObj*            errObj;
    size_t              nbytes = sizeof(UpFilter);
    UpFilter* const     filt = (UpFilter*)malloc(nbytes);

    if (NULL == filt) {
        errObj = ERR_NEW2(0, NULL, "Couldn't allocate %lu-bytes: %s",
            (unsigned long)nbytes, strerror(errno));
    }
    else {
        StringBuf* const strBuf = strBuf_new(132);

        if (NULL == strBuf) {
            errObj = ERR_NEW(0, NULL, strBuf_strerror(strBuf));

            free(filt);
        }
        else {
            filt->strBuf = strBuf;
            filt->head = NULL;
            filt->stringOutOfDate = 1;
            filt->count = 0;
            *upFilter = filt;
            errObj = NULL;              /* success */
        }
    }                                   /* "filt" allocated */

    return errObj;
}
Example #3
0
/*
 * Opens a shared-counter.
 *
 * Arguments:
 *      path    Pathname of the stat()able file to be associated with 
 *              the shared-counter.
 *      *sc     Pointer to shared-counter.  Set on and only on success.
 *
 * Returns:
 *      NULL    Success
 *      !NULL   Failure:
 *                      SC_SYSTEM
 */
ErrorObj*
sc_open(
    const char*                 path,
    SharedCounter** const       sc)
{
    ErrorObj*           error;
    size_t              nbytes = sizeof(SharedCounter);
    SharedCounter*      ptr = malloc(nbytes);

    if (NULL == ptr) {
        error = ERR_NEW2(SC_SYSTEM, NULL,
            "Couldn't allocate %lu bytes: %s",
            (unsigned long)nbytes, strerror(errno));
    }
    else {
        key_t   key = ftok(path, 0);

        if ((key_t)-1 == key) {
            error = ERR_NEW1(SC_SYSTEM, NULL,
                "Couldn't create key for shared-memory segment: %s",
                strerror(errno));
        }
        else {
            int shmid = shmget(key, sizeof(unsigned), 0600 | IPC_CREAT);

            if (-1 == shmid) {
                error = ERR_NEW1(SC_SYSTEM, NULL,
                    "Couldn't get shared-memory segment: %s", strerror(errno));
            }
            else {
                void* const     counter = shmat(shmid, NULL, 0);

                if ((void*)-1 == counter) {
                    error = ERR_NEW1(SC_SYSTEM, NULL,
                        "Couldn't attach shared-memory segment: %s",
                        strerror(errno));
                }
                else {
                    ptr->shmid = shmid;
                    ptr->counter = (unsigned*)counter;
                    *sc = ptr;
                    error = NULL;       /* success */
                }                       /* shared-memory segment attached */

                if (error)
                    (void)shmctl(shmid, IPC_RMID, NULL);
            }                           /* got shared-memory segment */
        }                               /* got key for shared memory segment */

        if (error)
            free(ptr);
    }                                   /* ptr allocated */

    return error;
}
Example #4
0
/*
 * Decodes a data-product signature from the last product-specification of a
 * product-class if it exists.
 *
 * Arguments:
 *      class           Pointer to the product-class.  Caller may free upon
 *                      return.
 * Returns:
 *      NULL            The last product-specification didn't contain a valid,
 *                      encoded signature.
 *      else            Pointer to a static signature buffer into which the
 *                      signature specification was successfully decoded.
 */
static const signaturet*
decodeSignature(
        const prod_class_t* const prodClass)
{
    const signaturet* sig = NULL; /* no valid, encoded signature */

    if (0 < prodClass->psa.psa_len) {
        const prod_spec* const lastProdSpec =
                &prodClass->psa.psa_val[prodClass->psa.psa_len - 1];

        if (NONE == lastProdSpec->feedtype) {
            char* pat = lastProdSpec->pattern;

            if (strncasecmp("SIG=", pat, 4) == 0) {
                char* encodedSig = pat + 4;
                int i;
                unsigned value;
                static signaturet sigBuf;

                errno = 0;

                for (i = 0; i < sizeof(signaturet); i++) {
                    if (sscanf(encodedSig + 2 * i, "%2x", &value) != 1)
                        break;

                    sigBuf[i] = (unsigned char) value;
                }

                if (i == sizeof(signaturet)) {
                    sig = (const signaturet*) &sigBuf[0];
                }
                else {
                    if (0 == errno) {
                        err_log_and_free(
                                ERR_NEW1(1, NULL, "Invalid signature (%s)",
                                        encodedSig), ERR_NOTICE);
                    }
                    else {
                        err_log_and_free(
                                ERR_NEW2(1, NULL, "Invalid signature (%s): %s",
                                        encodedSig, strerror(errno)),
                                ERR_NOTICE);
                    }
                } /* signature not decoded */
            } /* "SIG=" found */
        } /* last feedtype is NONE */
    } /* at least one product-specification */

    return sig;
}
Example #5
0
/*
 * Attempts to connect to an upstream LDM using a range of LDM versions.  The
 * versions are tried, in order, from highest to lowest.  This function returns
 * on the first successful attempt.  If the host is unknown or the RPC call
 * times-out, then the version-loop is prematurely terminated and this function
 * returns immediately.
 *
 * The client is responsible for freeing the client resources set by this
 * function on success.  Calls exitIfDone() after potentially lengthy
 * operations.
 *
 * Arguments:
 *   upName                The name of the upstream LDM host.
 *   port                  The port on which to connect.
 *   version               Program version.
 *   *client               Pointer to CLIENT structure. Set on success.
 *   *socket               The socket used for the connection.  May be NULL.
 *   *upAddr               The IP address of the upstream LDM host.  Set on
 *                         success.  May be NULL.
 * Returns:
 *    NULL                 Success.  *vers_out, *client, *sock_out, and *upAddr
 *                         set.
 *   !NULL                 Error. "*client" is not set. err_code(RETURN_VALUE):
 *       LDM_CLNT_UNKNOWN_HOST         Unknown upstream host.
 *       LDM_CLNT_TIMED_OUT            Call to upstream host timed-out.
 *       LDM_CLNT_BAD_VERSION          Upstream LDM isn't given version.
 *       LDM_CLNT_NO_CONNECT           Other connection-related error.
 *       LDM_CLNT_SYSTEM_ERROR         A fatal system-error occurred.
 */
ErrorObj*
ldm_clnttcp_create_vers(
    const char* const            upName,
    const unsigned               port,
    unsigned const               version,
    CLIENT** const               client,
    int* const                   socket,
    struct sockaddr_in*          upAddr)
{
    ErrorObj*           error;
    struct sockaddr_in  addr;

    log_assert(upName != NULL);
    log_assert(client != NULL);

    /*
     * Get the IP address of the upstream LDM.  This is a potentially
     * lengthy operation.
     */
    (void)exitIfDone(0);
    error = ldm_clnt_addr(upName, &addr);

    if (error) {
        error = ERR_NEW1(LDM_CLNT_UNKNOWN_HOST, error, 
            "Couldn't get IP address of host %s", upName);
    }
    else {
        int                     sock;
        int                     errCode;
        CLIENT*                 clnt = NULL;

        /*
         * Connect to the remote port.  This is a potentially lengthy
         * operation.
         */
        (void)exitIfDone(0);
        error = ldm_clnt_tcp_create(&addr, version, port, &clnt, &sock);

        if (error) {
            errCode = err_code(error);

            if (LDM_CLNT_NO_CONNECT != errCode) {
                error =
                    ERR_NEW3(errCode, error, 
                        "Couldn't connect to LDM %d on %s "
                            "using port %d",
                        version, upName, port);
            }
            else {
                err_log_and_free(
                    ERR_NEW3(0, error, 
                        "Couldn't connect to LDM %d on %s using port "
                            "%d",
                        version, upName, port),
                    ERR_INFO);

                /*
                 * Connect using the portmapper.  This is a
                 * potentially lengthy operation.
                 */
                (void)exitIfDone(0);
                error = ldm_clnt_tcp_create(&addr, version, 0, &clnt, &sock);

                if (error) {
                    error =
                        ERR_NEW2(err_code(error), error, 
                            "Couldn't connect to LDM on %s "
                            "using either port %d or portmapper",
                            upName, port);
                }                       /* portmapper failure */
            }                           /* non-fatal port failure */
        }                               /* port failure */

        if (!error) {
            /*
             * Success.  Set the return arguments.
             */
            *client = clnt;

            if (socket)
                *socket = sock;
            if (upAddr)
                *upAddr = addr;
        }
    }                                       /* got upstream IP address */

    return error;
}
Example #6
0
hiya_reply_t*
hiya_6_svc(
        prod_class_t *offered,
        struct svc_req *rqstp)
{
    const char* const pqfname = getQueuePath();
    static hiya_reply_t reply;
    SVCXPRT * const xprt = rqstp->rq_xprt;
    struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt);
    const char *upName = hostbyaddr(upAddr);
    int error;
    int isPrimary;
    unsigned int maxHereis;
    static prod_class_t *accept;

    /*
     * Open the product-queue for writing.  It will be closed by cleanup()
     * during process termination.
     */
    if (pq) {
        (void) pq_close(pq);
        pq = NULL;
    }
    error = pq_open(pqfname, PQ_DEFAULT, &pq);
    if (error) {
        err_log_and_free(ERR_NEW2(error, NULL,
                "Couldn't open product-queue \"%s\" for writing: %s",
                pqfname,
                PQ_CORRUPT == error
                ? "The product-queue is inconsistent"
                : strerror(error)), ERR_FAILURE);
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }

    /* else */

    error = down6_init(upName, upAddr, pqfname, pq);
    if (error) {
        uerror("Couldn't initialize downstream LDM");
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }
    else {
        uinfo("Downstream LDM initialized");
    }

    /*
     * The previous "accept" is freed here -- rather than freeing the
     * soon-to-be-allocated "accept" at the end of its block -- because it can
     * be used in the reply.
     */
    if (accept) {
        free_prod_class(accept); /* NULL safe */
        accept = NULL;
    }

    error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered,
            &accept, &isPrimary);

    maxHereis = isPrimary ? UINT_MAX : 0;

    if (error) {
        serror("Couldn't validate HIYA");
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }
    else {
        if (ulogIsDebug())
            udebug("intersection: %s", s_prod_class(NULL, 0, accept));

        if (accept->psa.psa_len == 0) {
            uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT "
                    "entries", upName, s_prod_class(NULL, 0, offered));
            svcerr_weakauth(xprt);
            svc_destroy(xprt);
            exit(0);
        }
        else {
            error = down6_set_prod_class(accept);

            if (error) {
                if (DOWN6_SYSTEM_ERROR == error) {
                    serror("Couldn't set product class: %s",
                            s_prod_class(NULL, 0, accept));
                }
                else {
                    uerror("Couldn't set product class: %s",
                            s_prod_class(NULL, 0, accept));
                }

                svcerr_systemerr(xprt);
                svc_destroy(xprt);
                exit(EXIT_FAILURE);
            }

            /* else */

            if (clss_eq(offered, accept)) {
                unotice("hiya6: %s", s_prod_class(NULL, 0, offered));

                reply.code = OK;
                reply.hiya_reply_t_u.max_hereis = maxHereis;
            }
            else {
                if (ulogIsVerbose()) {
                    char off[512];
                    char acc[512];

                    (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class(
                            acc, sizeof(acc), accept);

                    uinfo("hiya6: RECLASS: %s -> %s", off, acc);
                }

                reply.code = RECLASS;
                reply.hiya_reply_t_u.feedPar.prod_class = accept;
                reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis;
            }
        } /* product-intersection != empty set */
    } /* successful acl_check_hiya() */

    return &reply;
}
Example #7
0
/*
 * Adds a filter-component to an upstream-filter.
 *
 * Arguments:
 *      upFilter        Pointer to the upstream-filter to which to add the 
 *                      component.
 *      feedtype        The feedtype of the filter-component.
 *      okPattern       Pointer to the "OK pattern" of the filter-component to 
 *                      be added.  Caller may free upon return.
 *      notPattern      Pointer to the "not pattern" of the filter-component to
 *                      be added.  May be NULL to indicate that such matching
 *                      should be disabled.  Caller may free upon return.
 * Returns:
 *      NULL            Success.
 *      else            Error object.
 */
ErrorObj*
upFilter_addComponent(
    UpFilter* const             upFilter,
    const feedtypet             feedtype,
    const Pattern* const        okPattern,
    const Pattern* const        notPattern)
{
    ErrorObj*   errObj = NULL;          /* success */
    Element*    elt;

    /*
     * Ensure that the given feedtype is disjoint from all feedtypes already
     * in the filter.
     */
    for (elt = upFilter->head; NULL != elt; elt = elt->next) {
        if (feedtype & elt->ft) {
            char        ftSpec[512];

            (void)sprint_feedtypet(ftSpec, sizeof(ftSpec), feedtype);

            errObj = ERR_NEW2(0, NULL,
                "Feedtype %s overlaps with feedtype %s",
                ftSpec, s_feedtypet(elt->ft));

            break;
        }
    }

    if (NULL == errObj) {
        size_t          nbytes = sizeof(Element);

        elt = (Element*)malloc(nbytes);

        if (NULL == elt) {
            errObj = ERR_NEW2(0, NULL, "Couldn't allocate %lu-bytes: %s",
                (unsigned long)nbytes, strerror(errno));
        }
        else {
            if ((errObj = pat_clone(&elt->okPattern, okPattern))) {
                errObj = ERR_NEW(0, errObj, "Couldn't clone \"OK\" pattern");
                free(elt);
            }
            else {
                if (NULL == notPattern) {
                    elt->notPattern = NULL;
                }
                else {
                    if ((errObj = pat_clone(&elt->notPattern, notPattern))) {
                        errObj = ERR_NEW(0, errObj,
                            "Couldn't clone \"not\" pattern");
                        pat_free(elt->okPattern);
                        free(elt);
                        elt = NULL;
                    }
                }

                if (elt) {
                    elt->ft = feedtype;
                    elt->next = upFilter->head;
                    upFilter->head = elt;
                    upFilter->stringOutOfDate = 1;
                    upFilter->count++;
                }
            }                           /* "elt->okPattern" allocated */
        }                               /* "elt" allocated */
    } // given feedtype is disjoint from those already in filter

    return errObj;
}