pairmemcpy(vp, value, len);
}
+
+VALUE_PAIR *eap_chbind_packet2vp(REQUEST *request, const eap_chbind_packet_t *packet, size_t len)
+{
+ size_t size;
+ const uint8_t *ptr;
+ VALUE_PAIR *head = NULL;
+ uint8_t *octets = NULL;
+
+ VALUE_PAIR **tail = &head;
+ VALUE_PAIR *vp;
+
+ ptr = (const uint8_t *) packet;
+
+ do {
+ size = len;
+ if (size > 247) size = 247;
+
+ vp = paircreate(request, PW_UKERNA_CHBIND, VENDORPEC_UKERNA);
+ if (!vp) {
+ pairfree(&head);
+ return NULL;
+ }
+ octets = talloc_array(vp, uint8_t, size);
+ rad_assert(octets);
+ memcpy(octets, ptr, size);
+ vp->vp_octets = octets;
+ vp->length = size;
+
+ *tail = vp;
+ tail = &(vp->next);
+
+ ptr += size;
+ len -= size;
+ } while (len > 0);
+
+ return head;
+}
+
+
+/*
+ * Handles multiple EAP-channel-binding Message attrs
+ * ie concatenates all to get the complete EAP-channel-binding packet.
+ */
+size_t eap_chbind_vp2packet(VALUE_PAIR *vps, eap_chbind_packet_t **result)
+{
+ VALUE_PAIR *first, *vp;
+ eap_chbind_packet_t *eap_chbind_packet;
+ unsigned char *ptr;
+ size_t len;
+
+ first = pairfind(vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY);
+
+ /*
+ * Compute total length
+ */
+ len = 0;
+ for (vp = first; vp;
+ vp = pairfind(vp->next, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY)) {
+ len += vp->length;
+ }
+
+ /*
+ * Now that we know the length, allocate memory.
+ */
+ eap_chbind_packet = (eap_chbind_packet_t *) malloc(len);
+ if (eap_chbind_packet == NULL) {
+ radlog(L_ERR, "rlm_eap: out of memory");
+ return 0;
+ }
+
+ /*
+ * Copy the data from EAP-Message's over to our EAP packet.
+ */
+ ptr = (unsigned char *)eap_chbind_packet;
+
+ /* RADIUS ensures order of attrs, so just concatenate all */
+ for (vp = first; vp;
+ vp = pairfind(vp->next, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY)) {
+ memcpy(ptr, vp->vp_octets, vp->length);
+ ptr += vp->length;
+ }
+
+ *result = eap_chbind_packet;
+ return len;
+}