static void perl_vp_to_svpvn_element(REQUEST *request, AV *av, VALUE_PAIR const *vp, int *i, const char *hash_name, const char *list_name) { size_t len; char buffer[1024]; switch (vp->da->type) { case PW_TYPE_STRING: RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, vp->vp_strvalue); av_push(av, newSVpvn(vp->vp_strvalue, vp->vp_length)); break; case PW_TYPE_OCTETS: if (RDEBUG_ENABLED) { char *hex; hex = fr_abin2hex(request, vp->vp_octets, vp->vp_length); RDEBUG("$%s{'%s'}[%i] = &%s:%s -> 0x%s", hash_name, vp->da->name, *i, list_name, vp->da->name, hex); talloc_free(hex); } av_push(av, newSVpvn((char const *)vp->vp_octets, vp->vp_length)); break; default: len = fr_pair_value_snprint(buffer, sizeof(buffer), vp, 0); RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, buffer); av_push(av, newSVpvn(buffer, truncate_len(len, sizeof(buffer)))); break; } (*i)++; }
static void perl_vp_to_svpvn_element(REQUEST *request, AV *av, VALUE_PAIR const *vp, int *i, const char *hash_name, const char *list_name) { size_t len; SV *sv; char buffer[1024]; switch (vp->da->type) { case PW_TYPE_STRING: RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, vp->vp_strvalue); sv = newSVpvn(vp->vp_strvalue, vp->vp_length); break; default: len = vp_prints_value(buffer, sizeof(buffer), vp, 0); RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, buffer); sv = newSVpvn(buffer, truncate_len(len, sizeof(buffer))); break; } if (!sv) return; SvTAINTED_on(sv); av_push(av, sv); (*i)++; }
static void perl_vp_to_svpvn_element(REQUEST *request, AV *av, VALUE_PAIR const *vp, int *i, const char *hash_name, const char *list_name) { SV *sv; switch (vp->vp_type) { case FR_TYPE_STRING: RDEBUG2("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, vp->vp_strvalue); sv = newSVpvn(vp->vp_strvalue, vp->vp_length); break; case FR_TYPE_OCTETS: RDEBUG2("$%s{'%s'}[%i] = &%s:%s -> 0x%pH", hash_name, vp->da->name, *i, list_name, vp->da->name, &vp->data); sv = newSVpvn((char const *)vp->vp_octets, vp->vp_length); break; default: { char buffer[1024]; size_t len; len = fr_pair_value_snprint(buffer, sizeof(buffer), vp, '\0'); RDEBUG2("$%s{'%s'}[%i] = &%s:%s -> '%s'", hash_name, vp->da->name, *i, list_name, vp->da->name, buffer); sv = newSVpvn(buffer, truncate_len(len, sizeof(buffer))); } break; } if (!sv) return; SvTAINT(sv); av_push(av, sv); (*i)++; }
/* * get the vps and put them in perl hash * If one VP have multiple values it is added as array_ref * Example for this is Cisco-AVPair that holds multiple values. * Which will be available as array_ref in $RAD_REQUEST{'Cisco-AVPair'} */ static void perl_store_vps(UNUSED TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, HV *rad_hv, const char *hash_name, const char *list_name) { VALUE_PAIR *vp; hv_undef(rad_hv); fr_cursor_t cursor; RINDENT(); fr_pair_list_sort(vps, fr_pair_cmp_by_da_tag); for (vp = fr_cursor_init(&cursor, vps); vp; vp = fr_cursor_next(&cursor)) { VALUE_PAIR *next; char const *name; char namebuf[256]; /* * Tagged attributes are added to the hash with name * <attribute>:<tag>, others just use the normal attribute * name as the key. */ if (vp->da->flags.has_tag && (vp->tag != TAG_ANY)) { snprintf(namebuf, sizeof(namebuf), "%s:%d", vp->da->name, vp->tag); name = namebuf; } else { name = vp->da->name; } /* * We've sorted by type, then tag, so attributes of the * same type/tag should follow on from each other. */ if ((next = fr_cursor_next_peek(&cursor)) && ATTRIBUTE_EQ(vp, next)) { int i = 0; AV *av; av = newAV(); perl_vp_to_svpvn_element(request, av, vp, &i, hash_name, list_name); do { perl_vp_to_svpvn_element(request, av, next, &i, hash_name, list_name); fr_cursor_next(&cursor); } while ((next = fr_cursor_next_peek(&cursor)) && ATTRIBUTE_EQ(vp, next)); (void)hv_store(rad_hv, name, strlen(name), newRV_noinc((SV *)av), 0); continue; } /* * It's a normal single valued attribute */ switch (vp->vp_type) { case FR_TYPE_STRING: RDEBUG2("$%s{'%s'} = &%s:%s -> '%pV'", hash_name, vp->da->name, list_name, vp->da->name, &vp->data); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(vp->vp_strvalue, vp->vp_length), 0); break; case FR_TYPE_OCTETS: RDEBUG2("$%s{'%s'} = &%s:%s -> %pV", hash_name, vp->da->name, list_name, vp->da->name, &vp->data); (void)hv_store(rad_hv, name, strlen(name), newSVpvn((char const *)vp->vp_octets, vp->vp_length), 0); break; default: { char buffer[1024]; size_t len; len = fr_pair_value_snprint(buffer, sizeof(buffer), vp, '\0'); RDEBUG2("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name, list_name, vp->da->name, buffer); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(buffer, truncate_len(len, sizeof(buffer))), 0); } break; } } REXDENT(); }
/* * get the vps and put them in perl hash * If one VP have multiple values it is added as array_ref * Example for this is Cisco-AVPair that holds multiple values. * Which will be available as array_ref in $RAD_REQUEST{'Cisco-AVPair'} */ static void perl_store_vps(UNUSED TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR *vps, HV *rad_hv, const char *hashname, const char *list_name) { VALUE_PAIR *vp; hv_undef(rad_hv); vp_cursor_t cursor; RINDENT(); pairsort(&vps, attrtagcmp); for (vp = fr_cursor_init(&cursor, &vps); vp; vp = fr_cursor_next(&cursor)) { VALUE_PAIR *next; char const *name; char namebuf[256]; char buffer[1024]; size_t len; /* * Tagged attributes are added to the hash with name * <attribute>:<tag>, others just use the normal attribute * name as the key. */ if (vp->da->flags.has_tag && (vp->tag != TAG_ANY)) { snprintf(namebuf, sizeof(namebuf), "%s:%d", vp->da->name, vp->tag); name = namebuf; } else { name = vp->da->name; } /* * We've sorted by type, then tag, so attributes of the * same type/tag should follow on from each other. */ if ((next = fr_cursor_next_peek(&cursor)) && ATTRIBUTE_EQ(vp, next)) { int i; AV *av; av = newAV(); for (next = fr_cursor_next_by_da(&cursor, vp->da, vp->tag), i = 0; next; next = fr_cursor_next_by_da(&cursor, vp->da, vp->tag), i++) { switch (vp->da->type) { case PW_TYPE_STRING: RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hashname, next->da->name, i, list_name, next->da->name, next->vp_strvalue); av_push(av, newSVpvn(next->vp_strvalue, next->length)); break; case PW_TYPE_OCTETS: if (RDEBUG_ENABLED) { char *hex; hex = fr_abin2hex(request, next->vp_octets, next->length); RDEBUG("$%s{'%s'}[%i] = &%s:%s -> 0x%s", hashname, next->da->name, i, list_name, next->da->name, hex); talloc_free(hex); } av_push(av, newSVpvn((char const *)next->vp_octets, next->length)); break; default: len = vp_prints_value(buffer, sizeof(buffer), next, 0); RDEBUG("$%s{'%s'}[%i] = &%s:%s -> '%s'", hashname, next->da->name, i, list_name, next->da->name, buffer); av_push(av, newSVpvn(buffer, truncate_len(len, sizeof(buffer)))); break; } } (void)hv_store(rad_hv, name, strlen(name), newRV_noinc((SV *)av), 0); continue; } /* * It's a normal single valued attribute */ switch (vp->da->type) { case PW_TYPE_STRING: RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hashname, vp->da->name, list_name, vp->da->name, vp->vp_strvalue); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(vp->vp_strvalue, vp->length), 0); break; case PW_TYPE_OCTETS: if (RDEBUG_ENABLED) { char *hex; hex = fr_abin2hex(request, vp->vp_octets, vp->length); RDEBUG("$%s{'%s'} = &%s:%s -> 0x%s", hashname, vp->da->name, list_name, vp->da->name, hex); talloc_free(hex); } (void)hv_store(rad_hv, name, strlen(name), newSVpvn((char const *)vp->vp_octets, vp->length), 0); break; default: len = vp_prints_value(buffer, sizeof(buffer), vp, 0); RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hashname, vp->da->name, list_name, vp->da->name, buffer); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(buffer, truncate_len(len, sizeof(buffer))), 0); break; } } REXDENT(); }
/* * get the vps and put them in perl hash * If one VP have multiple values it is added as array_ref * Example for this is Cisco-AVPair that holds multiple values. * Which will be available as array_ref in $RAD_REQUEST{'Cisco-AVPair'} */ static void perl_store_vps(UNUSED TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, HV *rad_hv, const char *hash_name, const char *list_name) { VALUE_PAIR *vp; char *tbuff; size_t tbufflen = 1024; hv_undef(rad_hv); vp_cursor_t cursor; /* * Find out how much room to allocate. */ for (vp = fr_cursor_init(&cursor, vps); vp; vp = fr_cursor_next(&cursor)) { if (((vp->length * 2) + 3) > tbufflen) { tbufflen = (vp->vp_length * 2) + 3; } } tbuff = talloc_array(request, char, tbufflen); RINDENT(); fr_pair_list_sort(vps, fr_pair_cmp_by_da_tag); for (vp = fr_cursor_init(&cursor, vps); vp; vp = fr_cursor_next(&cursor)) { VALUE_PAIR *next; char const *name; size_t len; char namebuf[256]; /* * Tagged attributes are added to the hash with name * <attribute>:<tag>, others just use the normal attribute * name as the key. */ if (vp->da->flags.has_tag && (vp->tag != TAG_ANY)) { snprintf(namebuf, sizeof(namebuf), "%s:%d", vp->da->name, vp->tag); name = namebuf; } else { name = vp->da->name; } /* * We've sorted by type, then tag, so attributes of the * same type/tag should follow on from each other. */ if ((next = fr_cursor_next_peek(&cursor)) && ATTRIBUTE_EQ(vp, next)) { int i = 0; AV *av; av = newAV(); perl_vp_to_svpvn_element(request, av, vp, &i, hash_name, list_name); do { perl_vp_to_svpvn_element(request, av, next, &i, hash_name, list_name); fr_cursor_next(&cursor); } while ((next = fr_cursor_next_peek(&cursor)) && ATTRIBUTE_EQ(vp, next)); (void)hv_store(rad_hv, name, strlen(name), newRV_noinc((SV *)av), 0); continue; } /* * It's a normal single valued attribute */ switch (vp->da->type) { case PW_TYPE_STRING: RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name, list_name, vp->da->name, vp->vp_strvalue); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(vp->vp_strvalue, vp->vp_length), 0); break; default: len = vp_prints_value(tbuff, tbufflen, vp, 0); RDEBUG("$%s{'%s'} = &%s:%s -> '%s'", hash_name, vp->da->name, list_name, vp->da->name, tbuff); (void)hv_store(rad_hv, name, strlen(name), newSVpvn(tbuff, truncate_len(len, tbufflen)), 0); break; } } REXDENT(); talloc_free(tbuff); }