/* 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); }
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; }
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); }