示例#1
0
/* Fill the values for attribute type TLV */
void fill_type_attribute_tlv(struct tlv_type_len *type_len, struct attr_tlv *a_tlv, uint8_t ipaddr[IP_ADDR_SIZE])
{
    char ip[INET_ADDRSTRLEN];
    uint32_t ipaddr_32;
    type_len->type = TLV_ATTR_TYPE; /*2 for ATTR_TLV */
    type_len->len = ATTR_TLV_SIZE; /* 4 bytes for metric */
    /*convert the ip address stored in uint8_t[4] to uint32_t */
    u32fromu8(ipaddr, &ipaddr_32);
    //pthread_mutex_lock(&mutex_lock);
    if (print_msgs) {
        printf("Metric for ipaddr: %s: Decimal: %u, Hex:%06x,metric in nw format: %06x\n", inet_ntop(AF_INET, &ipaddr_32, ip, sizeof(ip)), find_metric(ipaddr_32), find_metric(ipaddr_32), htonl(find_metric(ipaddr_32)));
    }
// if(attr_metric == 0) /* No Metric given by user */
    a_tlv->metric = htonl(find_metric(ipaddr_32)); /* convert metric to nw byte order and store in structure */
// else
//	a_tlv->metric = htonl(attr_metric);
    //pthread_mutex_unlock(&mutex_lock);
}
示例#2
0
文件: dopdu.c 项目: aeppert/pcp
static int
do_control(__pmPDU *pb)
{
    int			sts;
    int			control;
    int			state;
    int			delta;
    pmResult		*request;
    pmResult		*result;
    int			siamised = 0;	/* the verb from siamese (as in twins) */
    int			i;
    int			j;
    int			val;
    pmValueSet		*vsp;
    optreq_t		*rqp;
    task_t		*tp;
    time_t		now;
    int			reqstate = 0;

    /*
     * TODO	- encoding for logging interval in requests and results?
     */
    if ((sts = __pmDecodeLogControl(pb, &request, &control, &state, &delta)) < 0)
	return sts;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOG) {
	fprintf(stderr, "do_control: control=%d state=%d delta=%d request ...\n",
		control, state, delta);
	dumpcontrol(stderr, request, 0);
    }
#endif

    if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) {
	time(&now);
	fprintf(stderr, "\n%s", ctime(&now));
	fprintf(stderr, "pmlc request from %s: %s",
	    pmlc_host, control == PM_LOG_MANDATORY ? "mandatory" : "advisory");
	if (state == PM_LOG_ON) {
	    if (delta == 0)
		fprintf(stderr, " on once\n");
	    else
		fprintf(stderr, " on %.1f sec\n", (float)delta/1000);
	}
	else if (state == PM_LOG_OFF)
	    fprintf(stderr, " off\n");
	else
	    fprintf(stderr, " maybe\n");
    }

    /*
     * access control checks
     */
    sts = 0;
    switch (control) {
	case PM_LOG_MANDATORY:
	    if (denyops & PM_OP_LOG_MAND)
		sts = PM_ERR_PERMISSION;
	    break;

	case PM_LOG_ADVISORY:
	    if (denyops & PM_OP_LOG_ADV)
		sts = PM_ERR_PERMISSION;
	    break;

	case PM_LOG_ENQUIRE:
	    /*
	     * Don't need to check [access] as you have to have _some_
	     * permission (at least one of PM_OP_LOG_ADV or PM_OP_LOG_MAND
	     * and PM_OP_LOG_ENQ) to make a connection ... and if you
	     * have either PM_OP_LOG_ADV or PM_OP_LOG_MAND it makes no
	     * sense to deny PM_OP_LOG_ENQ operations.
	     */
	    break;

	default:
	    fprintf(stderr, "Bad control PDU type %d\n", control);
	    sts = PM_ERR_IPC;
	    break;
    }
    if (sts < 0) {
	fprintf(stderr, "Error: %s\n", pmErrStr(sts));
	if ((sts = __pmSendError(clientfd, FROM_ANON, sts)) < 0)
	    __pmNotifyErr(LOG_ERR,
			 "do_control: error sending Error PDU to client: %s\n",
			 pmErrStr(sts));
	pmFreeResult(request);
	return sts;
    }

    /* handle everything except PM_LOG_ENQUIRE */
    if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) {
	/* update the logging status of metrics */

	task_t		*newtp = NULL; /* task for metrics/insts in request */
	struct timeval	tdelta = { 0 };
	int		newtask;
	int		mflags;

	/* convert state and control to the bitmask used in pmlogger and values
	 * returned in results.  Remember that reqstate starts with nothing on.
	 */
	if (state == PM_LOG_ON)
	    PMLC_SET_ON(reqstate, 1);
	else
	    PMLC_SET_ON(reqstate, 0);
	if (control == PM_LOG_MANDATORY) {
	    if (state == PM_LOG_MAYBE)
		/* mandatory+maybe => maybe+advisory+off  */
		PMLC_SET_MAYBE(reqstate, 1);
	    else
		PMLC_SET_MAND(reqstate, 1);
	}

	/* try to find an existing task for the request
	 * Never return a "once only" task, it may have gone off already and just
	 * be hanging around like a bad smell.
	 */
	if (delta != 0) {
	    tdelta.tv_sec = delta / 1000;
	    tdelta.tv_usec = (delta % 1000) * 1000;
	    newtp = find_task(reqstate, &tdelta);
	}
	newtask = (newtp == NULL);

	for (i = 0; i < request->numpmid; i++) {
	    vsp = request->vset[i];
	    if (vsp->numval < 0)
		/*
		 * request is malformed, as we cannot control logging
		 * for an undefined instance ... there is no way to
		 * return an error from here, so simply ignore this
		 * metric
		 */
		continue;
	    mflags = find_metric(vsp->pmid);
	    if (mflags < 0) {
		/* only add new metrics if they are ON or MANDATORY OFF
		 * Careful: mandatory+maybe is mandatory+maybe+off
		 */
		if (PMLC_GET_ON(reqstate) ||
		    (PMLC_GET_MAND(reqstate) && !PMLC_GET_MAYBE(reqstate)))
		    add_metric(vsp, &newtp);
	    }
	    else
		/* already a specification for this metric */
		update_metric(vsp, reqstate, mflags, &newtp);
	}

	/* schedule new logging task if new metric(s) specified */
	if (newtask && newtp != NULL) {
	    if (newtp->t_fetch == NULL) {
		/* the new task ended up with no fetch groups, throw it away */
		if (newtp->t_pmidlist != NULL)
		    free(newtp->t_pmidlist);
		free(newtp);
	    }
	    else {
		/* link new task into tasklist */
		newtp->t_next = tasklist;
		tasklist = newtp;

		/* use only the MAND/ADV and ON/OFF bits of reqstate */
		newtp->t_state = PMLC_GET_STATE(reqstate);
		if (PMLC_GET_ON(reqstate)) {
		    newtp->t_delta = tdelta;
		    newtp->t_afid = __pmAFregister(&tdelta, (void *)newtp,
					       log_callback);
		}
		else
		    newtp->t_delta.tv_sec = newtp->t_delta.tv_usec = 0;
		linkback(newtp);
	    }
	}
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_APPL0)
	dumpit();
#endif

    /* just ignore advisory+maybe---the returned pmResult will have the metrics
     * in their original state indicating that the request could not be
     * satisfied.
     */

    result = request;
    result->timestamp.tv_sec = result->timestamp.tv_usec = 0;	/* for purify */
    /* write the current state of affairs into the result _pmResult */
    for (i = 0; i < request->numpmid; i++) {

	if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) {
	    char	**names;

	    sts = pmNameAll(request->vset[i]->pmid, &names);
	    if (sts < 0)
		fprintf(stderr, "  metric: %s", pmIDStr(request->vset[i]->pmid));
	    else {
		fprintf(stderr, "  metric: ");
		__pmPrintMetricNames(stderr, sts, names, " or ");
		free(names);
	    }
	}

	if (request->vset[i]->numval <= 0 && !siamised) {
	    result = siamise_request(request);
	    siamised = 1;
	}
	/*
	 * pmids with numval <= 0 in the request have a null vset ptr in the
	 * in the corresponding place in the siamised result.
	 */
	if (result->vset[i] != NULL)
	    vsp = result->vset[i];
	else {
	    /* the result should also contain the history for an all instances
	     * enquire request.  Control requests just get the current indom
	     * since the user of pmlc really wants to see what's being logged
	     * now rather than in the past.
	     */
	    vsp = build_vset(request->vset[i]->pmid, control == PM_LOG_ENQUIRE);
	    result->vset[i] = vsp;
	}
	vsp->valfmt = PM_VAL_INSITU;
	for (j = 0; j < vsp->numval; j++) {
	    rqp = findoptreq(vsp->pmid, vsp->vlist[j].inst);
	    val = 0;
	    if (rqp == NULL) {
		PMLC_SET_STATE(val, 0);
		PMLC_SET_DELTA(val, 0);
	    }
	    else {
		tp = rqp->r_fetch->f_aux;
		PMLC_SET_STATE(val, tp->t_state);
		PMLC_SET_DELTA(val, (tp->t_delta.tv_sec*1000 + tp->t_delta.tv_usec/1000));
	    }

	    val |= gethistflags(vsp->pmid, vsp->vlist[j].inst);
	    vsp->vlist[j].value.lval = val;

	    if (control == PM_LOG_MANDATORY || control == PM_LOG_ADVISORY) {
		int	expstate = 0;
		int	statemask = 0;
		int	expdelta;
		if (rqp != NULL && rqp->r_desc->indom != PM_INDOM_NULL) {
		    char	*p;
		    if (j == 0)
			fputc('\n', stderr);
		    if (pmNameInDom(rqp->r_desc->indom, vsp->vlist[j].inst, &p) >= 0) {
			fprintf(stderr, "    instance: %s", p);
			free(p);
		    }
		    else
			fprintf(stderr, "    instance: #%d", vsp->vlist[j].inst);
		}
		else {
		    /* no pmDesc ... punt */
		    if (vsp->numval > 1 || vsp->vlist[j].inst != PM_IN_NULL) {
			if (j == 0)
			    fputc('\n', stderr);
			fprintf(stderr, "    instance: #%d", vsp->vlist[j].inst);
		    }
		}
		if (state != PM_LOG_MAYBE) {
		    if (control == PM_LOG_MANDATORY)
			PMLC_SET_MAND(expstate, 1);
		    else
			PMLC_SET_MAND(expstate, 0);
		    if (state == PM_LOG_ON)
			PMLC_SET_ON(expstate, 1);
		    else
			PMLC_SET_ON(expstate, 0);
		    PMLC_SET_MAND(statemask, 1);
		    PMLC_SET_ON(statemask, 1);
		}
		else {
		    PMLC_SET_MAND(expstate, 0);
		    PMLC_SET_MAND(statemask, 1);
		}
		expdelta = PMLC_GET_ON(expstate) ? delta : 0;
		if ((PMLC_GET_STATE(val) & statemask) != expstate ||
		    PMLC_GET_DELTA(val) != expdelta)
			fprintf(stderr, " [request failed]");
		fputc('\n', stderr);
	    }
	}
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_LOG) {
	__pmDumpResult(stderr, result);
    }
#endif

    if ((sts = __pmSendResult(clientfd, FROM_ANON, result)) < 0)
		__pmNotifyErr(LOG_ERR,
			     "do_control: error sending Error PDU to client: %s\n",
			     pmErrStr(sts));

    if (siamised) {
	for (i = 0; i < request->numpmid; i++)
	    if (request->vset[i]->numval <= 0)
		free(result->vset[i]);
	free(result);
    }
    pmFreeResult(request);

    return 0;
}
示例#3
0
int larp_reply_pkt(struct arphdr *ar_hdr, struct sockaddr_ll *recv_addr)
{
    int send_sockfd;
    int i, send_bytes, frame_length;
    uint32_t ipaddr_n32;
    //char ipaddr_p[INET_ADDRSTRLEN]; /* to print IP address in presentation format */
    struct sockaddr_ll send_addr;
    struct arphdr send_arhdr; /* standard ARP header fields */
    struct tlv_type_len type_len; /* variable of type-len struct */
    struct label_stack *l_stack = (struct label_stack *) malloc(label_count * sizeof(struct label_stack)); /* For label stack */
    struct attr_tlv a_tlv; /* For Attributes TLV */
    char if_name[IFNAMSIZ];
    uint32_t metric_val;
    unsigned char *s_haddr = allocate_ustrmem (6);
    /*create a RAW PF_PACKET socket for sending out the reply*/
    send_sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
    if (send_sockfd < 0) { /* socket function returns negative value on error */
        printf("Sending socket creation failed\n");
        exit(1);
    }
    uint8_t *buffer = allocate_ustrmem (IP_MAXPACKET);
    /* Making the buffer all zeros */
    memset(buffer, 0, ETH_FRAME_LEN);
    /* Get the local interface MAC address based on the received interface index*/
    get_mac (recv_addr->sll_ifindex, s_haddr);
    /*zeroing out the struct sockaddr_ll structure*/
    memset(&send_addr, 0, sizeof(struct sockaddr_ll));
    /* Fill in the values for struct sockaddr_ll structure*/

    send_addr.sll_family = PF_PACKET;
    send_addr.sll_protocol = htons(ETH_P_ARP);
    send_addr.sll_ifindex = recv_addr->sll_ifindex;
    send_addr.sll_halen = ETH_ALEN; /*6 bytes for Mac address */
    /* filling target MAC address from source MAC field of received LARP req */
    send_addr.sll_addr[0] = ar_hdr->ar_sha[0];
    send_addr.sll_addr[1] = ar_hdr->ar_sha[1];
    send_addr.sll_addr[2] = ar_hdr->ar_sha[2];
    send_addr.sll_addr[3] = ar_hdr->ar_sha[3];
    send_addr.sll_addr[4] = ar_hdr->ar_sha[4];
    send_addr.sll_addr[5] = ar_hdr->ar_sha[5];
    /* Not used */
    send_addr.sll_addr[6] = 0x00;
    send_addr.sll_addr[7] = 0x00;
#if 0
    for (i=0; i<5; i++)
        printf("%02x:", s_haddr[i]);
    printf("%02x\n", s_haddr[i]);
#endif

    /* Start filling the buffer starting with Ethernet header */

    /* Fill in ethernet header*/
    memcpy(buffer, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t)); /* destination MAC*/
    memcpy(buffer + ETH_ALEN, s_haddr, ETH_ALEN * sizeof(uint8_t)); /* source MAC */
    /* Fill ETH_TYPE = ETH_P_ARP for ARP */
    buffer[12] = ETH_P_ARP / 256;
    buffer[13] = ETH_P_ARP % 256;
    /*Fill in ARP header fileds */
    send_arhdr.ar_htype = htons(ARPHRD_LARP);
    send_arhdr.ar_ptype = htons(ETH_P_IP); /* code for IPV6 can be added as needed*/
    send_arhdr.ar_hln = ETH_ALEN;
    send_arhdr.ar_pln = IP_ADDR_SIZE;
    send_arhdr.ar_op = htons(LARP_REPLY_OP); /* LARP reply = 2 */
    /* source and destination MAC address */
    memcpy(&send_arhdr.ar_sha, s_haddr, ETH_ALEN * sizeof(uint8_t));
    memcpy(&send_arhdr.ar_tha, ar_hdr->ar_sha, ETH_ALEN * sizeof(uint8_t));
    /* Source and destination IP filled using received LARP request */
    memcpy(&send_arhdr.ar_sip, ar_hdr->ar_tip, IP_ADDR_SIZE * sizeof(uint8_t));
    memcpy(&send_arhdr.ar_tip, ar_hdr->ar_sip, IP_ADDR_SIZE * sizeof(uint8_t));

    /* Copying ARP header to sending packet buffer */
    memcpy(buffer + ETH_HDR_SIZE, &send_arhdr, sizeof(struct arphdr));

    /*Fill in type, length and label for TLV_LST */
    fill_type_label_stack(&type_len, l_stack, ar_hdr->ar_tip);

    /* copy the tlv TLV_LST struct to sending buffer */
    memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE, &type_len, TYPE_LEN_SIZE);
    memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE, l_stack, label_count * LABEL_STACK_SIZE);

    /*Add Attribute TLV to sending buffer only if it is enabled */
    if(attr_tlv_flag) {
        /* zero the type_len struct so that now the new values can be held for attr_tlv*/
        memset (&type_len, 0, TYPE_LEN_SIZE);

        /* Fill in struct values for attributes TLV */
        fill_type_attribute_tlv(&type_len, &a_tlv, ar_hdr->ar_tip);
        /* Copy the ATTR_TLV struct to the sending buffer */
        memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE, &type_len, TYPE_LEN_SIZE);
        memcpy(buffer + ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + TYPE_LEN_SIZE, &a_tlv, ATTR_TLV_SIZE);
    }

    /* Frame length = Ethernet header + ARP header + type_len + label_stack */
    frame_length = ETH_HDR_SIZE + ARP_HDR_SIZE + TYPE_LEN_SIZE + label_count * LABEL_STACK_SIZE + attr_tlv_flag * (TYPE_LEN_SIZE + ATTR_TLV_SIZE);

    /* sending the filled packet buffer using sendto*/
    send_bytes = sendto(send_sockfd, buffer, frame_length, 0, (SA *) &send_addr, sizeof(send_addr));
    if(send_bytes <= 0) { /* Return value: 0 is no bytes sent and negative is error */
        perror("Sendto() for LARP reply failed\n");
        exit (1);
    }
    get_interface_name (send_addr.sll_ifindex, if_name);
    printf("Sent LARP reply to %u.%u.%u.%u for target %u.%u.%u.%u on interface: %s with label(s): ", send_arhdr.ar_tip[0], send_arhdr.ar_tip[1], send_arhdr.ar_tip[2], send_arhdr.ar_tip[3], send_arhdr.ar_sip[0], send_arhdr.ar_sip[1], send_arhdr.ar_sip[2], send_arhdr.ar_sip[3],if_name);
    u32fromu8(send_arhdr.ar_sip, &ipaddr_n32);
    uint32_t *label_stk = (uint32_t *) calloc (0, label_count * sizeof(uint32_t));
    memcpy(label_stk, find_label(ipaddr_n32), label_count * sizeof(uint32_t));
    print_label_stack(label_stk);
    metric_val = find_metric(ipaddr_n32);
    if (metric_val != 0)
        printf("and with metric: %u\n", find_metric(ipaddr_n32));
    else
        printf("and with no ATTR_TLV.\n");
    if (hex_dump_flag) /* print hex_dump of packet if flag enabled */
        hexDump (ntohs(send_arhdr.ar_op), buffer+14 , frame_length - 14);
    /* freeing dynamically allocated memory */
    free (label_stk);
    free(s_haddr);
    free(l_stack);
}