} VALUE_PAIR;
+typedef struct vp_cursor {
+ VALUE_PAIR **root; //!< Currently unused.
+ VALUE_PAIR *last; //!< Temporary only use for pairinsert
+ VALUE_PAIR *next; //!< Next attribute to process.
+} vp_cursor_t;
+
typedef struct value_pair_raw {
char l_opand[64]; //!< Left hand side of the
//!< pair.
VALUE_PAIR *paircreate(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor);
int pair2unknown(VALUE_PAIR *vp);
void pairfree(VALUE_PAIR **);
-void pairbasicfree(VALUE_PAIR *pair);
+void pairbasicfree(VALUE_PAIR *pair);
VALUE_PAIR *pairfind(VALUE_PAIR *, unsigned int attr, unsigned int vendor, int8_t tag);
+
+#define paircursor(_x, _y) paircursorc(_x,(VALUE_PAIR const * const *) _y)
+VALUE_PAIR *paircursorc(vp_cursor_t *cursor, VALUE_PAIR const * const *node);
+VALUE_PAIR *pairfirst(vp_cursor_t *cursor);
+VALUE_PAIR *pairfindnext(vp_cursor_t *cursor, unsigned int attr, unsigned int vendor, int8_t tag);
+VALUE_PAIR *pairnext(vp_cursor_t *cursor);
+VALUE_PAIR *pairlast(vp_cursor_t *cursor);
+VALUE_PAIR *paircurrent(vp_cursor_t *cursor);
+void pairinsert(vp_cursor_t *cursor, VALUE_PAIR *vp);
void pairdelete(VALUE_PAIR **, unsigned int attr, unsigned int vendor, int8_t tag);
void pairadd(VALUE_PAIR **, VALUE_PAIR *);
-void pairreplace(VALUE_PAIR **first, VALUE_PAIR *add);
+void pairreplace(VALUE_PAIR **first, VALUE_PAIR *add);
int paircmp(VALUE_PAIR *check, VALUE_PAIR *data);
int paircmp_op(VALUE_PAIR const *one, FR_TOKEN op, VALUE_PAIR const *two);
VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp);
*/
void vp_printlist(FILE *fp, VALUE_PAIR const *vp)
{
- for (; vp; vp = vp->next) {
+ vp_cursor_t cursor;
+ for (vp = paircursorc(&cursor, &vp); vp; vp = pairnext(&cursor)) {
vp_print(fp, vp);
}
}
*/
void pairfree(VALUE_PAIR **vps)
{
- VALUE_PAIR *next, *vp;
-
- if (!vps) return;
- vp = *vps;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
- while (vp) {
+ if (!vps) {
+ return;
+ }
+
+ for (vp = paircursor(&cursor, vps);
+ vp;
+ vp = pairnext(&cursor)) {
VERIFY(vp);
- next = vp->next;
pairbasicfree(vp);
- vp = next;
}
*vps = NULL;
* @todo should take DAs and do a pointer comparison.
*/
VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor,
- int8_t tag)
+ int8_t tag)
{
- while (vp) {
- VERIFY(vp);
- if ((vp->da->attr == attr) && (vp->da->vendor == vendor)
- && ((tag == TAG_ANY) || (vp->da->flags.has_tag &&
- (vp->tag == tag)))) {
- return vp;
+ vp_cursor_t cursor;
+ VALUE_PAIR *i;
+
+ for (i = paircursor(&cursor, &vp);
+ i;
+ i = pairnext(&cursor)) {
+ VERIFY(i);
+ if ((i->da->attr == attr) && (i->da->vendor == vendor)
+ && ((tag == TAG_ANY) || (i->da->flags.has_tag &&
+ (i->tag == tag)))) {
+ return i;
}
- vp = vp->next;
}
return NULL;
}
+/** Setup a cursor to iterate over attribute pairs
+ *
+ * @param cursor Where to initialise the cursor (uses existing structure).
+ * @param node to start from.
+ */
+VALUE_PAIR *paircursorc(vp_cursor_t *cursor, VALUE_PAIR const * const *node)
+{
+ memset(cursor, 0, sizeof(*cursor));
+
+ if (!node || !cursor) {
+ return NULL;
+ }
+
+ memcpy(&cursor->root, &node, sizeof(cursor->root));
+ cursor->next = *cursor->root;
+
+ return cursor->next;
+}
+
+VALUE_PAIR *pairfirst(vp_cursor_t *cursor)
+{
+ cursor->next = *cursor->root;
+
+ return cursor->next;
+}
+
+/** Iterate over attributes of a given type in the pairlist
+ *
+ *
+ */
+VALUE_PAIR *pairfindnext(vp_cursor_t *cursor, unsigned int attr, unsigned int vendor, int8_t tag)
+{
+ VALUE_PAIR *i;
+
+ i = pairfind(cursor->next, attr, vendor, tag);
+ if (i) {
+ cursor->next = i->next;
+ }
+
+ return i;
+}
+
+/** Retrieve the next VALUE_PAIR
+ *
+ *
+ */
+VALUE_PAIR *pairnext(vp_cursor_t *cursor)
+{
+ if (!cursor->next) {
+ return NULL;
+ }
+
+ cursor->next = cursor->next->next;
+
+ return cursor->next;
+}
+
+VALUE_PAIR *paircurrent(vp_cursor_t *cursor)
+{
+ return cursor->next;
+}
+
+/** Insert a VP
+ *
+ * @todo don't use with pairdelete
+ */
+void pairinsert(vp_cursor_t *cursor, VALUE_PAIR *add)
+{
+ VALUE_PAIR *i;
+
+ if (!add) {
+ return;
+ }
+
+ VERIFY(add);
+
+ /*
+ * Cursor was initialised with a pointer to a NULL value_pair
+ */
+ if (!*cursor->root) {
+ *cursor->root = add;
+ cursor->next = add;
+ cursor->last = add;
+
+ return;
+ }
+
+ /*
+ * We don't yet know where the last VALUE_PAIR is
+ */
+ if (!cursor->last) {
+ for (i = cursor->next; i; i = i->next) {
+ cursor->last = VERIFY(i);
+ }
+ }
+
+ /*
+ * Something outside of the cursor added another VALUE_PAIR
+ */
+ if (cursor->last->next) {
+ for (i = cursor->last; i; i = i->next) {
+ cursor->last = VERIFY(i);
+ }
+ }
+
+ cursor->last->next = add;
+}
/** Delete matching pairs
*
*/
static int rad_check_password(REQUEST *request)
{
+ vp_cursor_t cursor;
VALUE_PAIR *auth_type_pair;
- VALUE_PAIR *cur_config_item;
int auth_type = -1;
int result;
int auth_type_count = 0;
* if the authentication type is PW_AUTHTYPE_ACCEPT or
* PW_AUTHTYPE_REJECT.
*/
- cur_config_item = request->config_items;
- while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE, 0, TAG_ANY))) != NULL) {
+ paircursor(&cursor, &request->config_items);
+ while ((auth_type_pair = pairfindnext(&cursor, PW_AUTH_TYPE, 0, TAG_ANY))) {
auth_type = auth_type_pair->vp_integer;
auth_type_count++;
- RDEBUG2("Found Auth-Type = %s",
- dict_valnamebyattr(PW_AUTH_TYPE, 0, auth_type));
- cur_config_item = auth_type_pair->next;
-
+ RDEBUG2("Found Auth-Type = %s", dict_valnamebyattr(PW_AUTH_TYPE, 0, auth_type));
if (auth_type == PW_AUTHTYPE_REJECT) {
RDEBUG2("Auth-Type = Reject, rejecting user");
+
return -2;
}
}
* Warn if more than one Auth-Type was found, because only the last
* one found will actually be used.
*/
- if (( auth_type_count > 1) && (debug_flag)) {
+ if ((auth_type_count > 1) && (debug_flag)) {
RERROR("Warning: Found %d auth-types on request for user '%s'",
auth_type_count, request->username->vp_strvalue);
}
static int null_socket_send(UNUSED rad_listen_t *listener, REQUEST *request)
{
+ vp_cursor_t cursor;
char *output_file;
FILE *fp;
VALUE_PAIR *vp;
request->reply->code, request->reply->id);
}
- for (vp = request->reply->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, request->reply->vps);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(buffer, sizeof(buffer), vp);
fprintf(fp, "%s\n", buffer);
if (debug_flag) {
fr_command_socket_t *sock = listener->data;
rad_listen_t *fake;
RADIUS_PACKET *packet;
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
FILE *fp;
RAD_REQUEST_FUNP fun = NULL;
buffer, sizeof(buffer)),
packet->code, packet->id);
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(buffer, sizeof(buffer), vp);
DEBUG("\t%s", buffer);
}
int detail_recv(rad_listen_t *listener)
{
char key[256], op[8], value[1024];
- VALUE_PAIR *vp, **tail;
+ vp_cursor_t cursor;
+ VALUE_PAIR *vp;
RADIUS_PACKET *packet;
char buffer[2048];
listen_detail_t *data = listener->data;
goto do_header;
}
- tail = &data->vps;
- while (*tail) tail = &(*tail)->next;
+ paircursor(&cursor, &data->vps);
/*
* Read a header, OR a value-pair.
vp = paircreate(data, PW_PACKET_ORIGINAL_TIMESTAMP, 0);
if (vp) {
vp->vp_date = (uint32_t) data->timestamp;
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
}
continue;
}
vp = NULL;
if ((userparse(data, buffer, &vp) > 0) &&
(vp != NULL)) {
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
}
}
if (debug_flag) {
fr_printf_log("detail_recv: Read packet from %s\n", data->filename_work);
- for (vp = packet->vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
debug_pair(vp);
}
}
void radius_pairmove(REQUEST *request, VALUE_PAIR **to, VALUE_PAIR *from)
{
int i, j, count, from_count, to_count, tailto;
+ vp_cursor_t cursor;
VALUE_PAIR *vp, *next, **last;
VALUE_PAIR **from_list, **to_list;
int *edited = NULL;
* the matching attributes are deleted.
*/
count = 0;
- for (vp = from; vp != NULL; vp = vp->next) count++;
+ for (vp = paircursor(&cursor, &from); vp; vp = pairnext(&cursor)) count++;
from_list = rad_malloc(sizeof(*from_list) * count);
- for (vp = *to; vp != NULL; vp = vp->next) count++;
+ for (vp = paircursor(&cursor, *to); vp; vp = pairnext(&cursor)) count++;
to_list = rad_malloc(sizeof(*to_list) * count);
/*
envp[0] = NULL;
if (input_pairs) {
+ vp_cursor_t cursor;
int envlen;
char buffer[1024];
*/
envlen = 0;
- for (vp = input_pairs; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &input_pairs); vp; vp = pairnext(&cursor)) {
/*
* Hmm... maybe we shouldn't pass the
* user's password in an environment
*/
void vp_listdebug(VALUE_PAIR *vp)
{
+ vp_cursor_t cursor;
char tmpPair[70];
- for (; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &vp);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(tmpPair, sizeof(tmpPair), vp);
DEBUG2(" %s", tmpPair);
}
*/
int modcall(int component, modcallable *c, REQUEST *request)
{
+ vp_cursor_t cursor;
int myresult, mypriority;
modcall_stack stack;
modcallable *parent, *child;
if (myresult == MOD_ACTION_RETURN) {
break;
}
- vp = pairfind(vp->next, vp->da->attr,
- vp->da->vendor, TAG_ANY);
+ paircursor(&cursor, &vp);
+ vp = pairfindnext(&cursor, vp->da->attr, vp->da->vendor, TAG_ANY);
/*
* Delete the cached attribute,
static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
{
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
char buffer[1024];
char const *received, *from;
packet->code, packet->id, packet->data_len);
}
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(buffer, sizeof(buffer), vp);
RDEBUG("\t%s", buffer);
}
*/
vp = pairfind(request->proxy->vps, PW_USER_NAME, 0, TAG_ANY);
if (!vp) {
+ vp_cursor_t cursor;
vp = radius_paircreate(request, NULL,
PW_USER_NAME, 0);
rad_assert(vp != NULL); /* handled by above function */
/* Insert at the START of the list */
- vp->next = request->proxy->vps;
+ /* FIXME: Can't make assumptions about ordering */
+ paircursor(&cursor, vp);
+ pairinsert(&cursor, request->proxy->vps);
request->proxy->vps = vp;
}
pairstrcpy(vp, strippedname->vp_strvalue);
* it if so.
*/
if (head) {
+ vp_cursor_t cursor;
p = output;
- for (vp = head; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &head);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(p, sizeof(output) - (p - output), vp);
p += strlen(p);
static int radclient_init(char const *filename)
{
FILE *fp;
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
radclient_t *radclient;
int filedone = 0;
/*
* Fix up Digest-Attributes issues
*/
- for (vp = radclient->request->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &radclient->request->vps);
+ vp;
+ vp = pairnext(&cursor)) {
if (!vp->da->vendor) switch (vp->da->attr) {
default:
break;
radclient->packet_number, radclient->filename);
return -1;
}
-
radclient->request->code = packet_code;
}
radclient->request->sockfd = -1;
static int filter_packet(RADIUS_PACKET *packet)
{
+ vp_cursor_t cursor, check_cursor;
VALUE_PAIR *check_item;
VALUE_PAIR *vp;
unsigned int pass, fail;
int compare;
pass = fail = 0;
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
- for (check_item = filter_vps;
- check_item != NULL;
- check_item = check_item->next)
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
+ for (check_item = paircursor(&check_cursor, &filter_vps);
+ check_item;
+ check_item = pairnext(&check_cursor))
if ((check_item->da == vp->da)
&& (check_item->op != T_OP_SET)) {
compare = paircmp(check_item, vp);
static void sort(RADIUS_PACKET *packet)
{
int i, j, size;
+ vp_cursor_t cursor;
VALUE_PAIR *vp, *tmp;
VALUE_PAIR *array[1024]; /* way more than necessary */
size = 0;
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
array[size++] = vp;
}
if (vp_file == NULL) {
RDEBUG2("Could not write session VPs to persistent cache: %s", strerror(errno));
} else {
+ vp_cursor_t cursor;
/* generate a dummy user-style entry which is easy to read back */
fprintf(vp_file, "# SSL cached session\n");
fprintf(vp_file, "%s\n", buffer);
- for (vp=vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, vps);
+ vp;
+ vp = pairnext(&cursor)) {
vp_prints(buf, sizeof(buf), vp);
- fprintf(vp_file, "\t%s%s\n", buf, vp->next ? "," : "");
+ fprintf(vp_file, "\t%s%s\n", buf, ",");
}
fclose(vp_file);
}
return -1;
} else {
- RDEBUG("Adding cached attributes for session %s:",
- buffer);
+ vp_cursor_t cursor;
+
+ RDEBUG("Adding cached attributes for session %s:", buffer);
debug_pair_list(vps);
- for (vp = vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, vps);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* TLS-* attrs get added back to
* the request list.
int paircompare(REQUEST *request, VALUE_PAIR *req_list, VALUE_PAIR *check,
VALUE_PAIR **rep_list)
{
+ vp_cursor_t cursor;
VALUE_PAIR *check_item;
VALUE_PAIR *auth_item;
int compare;
int other;
- for (check_item = check;
- check_item != NULL;
- check_item = check_item->next) {
+ for (check_item = paircursor(&cursor, check);
+ check_item;
+ check_item = pairnext(&cursor)) {
/*
* If the user is setting a configuration value,
* then don't bother comparing it to any attributes
try_again:
if (other >= 0) {
while (auth_item != NULL) {
- if ((auth_item->da->attr ==
- (unsigned int) other) ||
- (other == 0)) {
+ if ((auth_item->da->attr == (unsigned int) other) || (other == 0)) {
break;
}
auth_item = auth_item->next;
*/
void debug_pair_list(VALUE_PAIR *vp)
{
+ vp_cursor_t cursor;
if (!vp || !debug_flag || !fr_log_fp) return;
- while (vp) {
+ for (vp = paircursor(&cursor, &vp);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* Take this opportunity to verify all the VALUE_PAIRs are still valid.
*/
}
vp_print(fr_log_fp, vp);
- vp = vp->next;
}
fflush(fr_log_fp);
}
*/
void rdebug_pair_list(int level, REQUEST *request, VALUE_PAIR *vp)
{
+ vp_cursor_t cursor;
char buffer[256];
if (!vp || !request || !request->radlog) return;
- while (vp) {
+ for (vp = paircursor(&cursor, &vp);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* Take this opportunity to verify all the VALUE_PAIRs are still valid.
*/
vp_prints(buffer, sizeof(buffer), vp);
request->radlog(L_DBG, level, request, "\t%s", buffer);
- vp = vp->next;
}
}
int radius_map2request(REQUEST *request, value_pair_map_t const *map,
UNUSED char const *src, radius_tmpl_getvalue_t func, void *ctx)
{
+ vp_cursor_t cursor;
VALUE_PAIR **list, *vp, *head;
char buffer[MAX_STRING_LEN];
return -1;
}
- if (debug_flag) for (vp = head; vp != NULL; vp = vp->next) {
+ if (debug_flag) for (vp = paircursor(&cursor, &head); vp; vp = pairnext(&cursor)) {
rad_assert(vp->op == map->op);
vp_prints_value(buffer, sizeof(buffer), vp, 1);
static int decode_tlv(RADIUS_PACKET *packet, VALUE_PAIR *tlv, uint8_t const *data, size_t data_len)
{
const uint8_t *p;
- VALUE_PAIR *head, **tail, *vp;
+ VALUE_PAIR *head, *vp;
+ vp_cursor_t cursor;
/*
* Take a pass at parsing it.
* Got here... must be well formed.
*/
head = NULL;
- tail = &head;
-
+ paircursor(&cursor, &head);
+
p = data;
while (p < (data + data_len)) {
vp = paircreate(packet, tlv->da->attr | (p[0] << 8), DHCP_MAGIC_VENDOR);
goto make_tlv;
}
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
p += 2 + p[1];
}
uint8_t const *data, size_t len, VALUE_PAIR **head)
{
int i;
- VALUE_PAIR *vp, **tail;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
uint8_t const *p, *next;
next = data;
*head = NULL;
- tail = head;
+ paircursor(&cursor, &head);
+
/*
* FIXME: This should also check sname && file fields.
* See the dhcp_get_option() function above.
return -1;
}
- *tail = vp;
- while (*tail) {
- debug_pair(*tail);
- tail = &(*tail)->next;
+ pairinsert(&cursor, vp);
+
+ for (vp = paircurrent(&cursor);
+ vp;
+ vp = pairnext(&cursor)) {
+ debug_pair(vp);
}
p += alen;
} /* loop over array entries */
size_t i;
uint8_t *p;
uint32_t giaddr;
- VALUE_PAIR *head, *vp, **tail;
+ vp_cursor_t cursor;
+ VALUE_PAIR *head, *vp;
VALUE_PAIR *maxms, *mtu;
head = NULL;
- tail = &head;
+ paircursor(&cursor, &head);
p = packet->data;
if ((fr_debug_flag > 2) && fr_log_fp) {
if (!vp) continue;
debug_pair(vp);
- *tail = vp;
- tail = &vp->next;
+ pairinsert(&cursor, vp);
}
/*
* Nothing uses tail after this call, if it does in the future
* it'll need to find the new tail...
*/
- if (fr_dhcp_decode_options(packet,
- packet->data + 240, packet->data_len - 240,
- tail) < 0) {
- return -1;
+ {
+ VALUE_PAIR *options = NULL;
+
+ if (fr_dhcp_decode_options(packet,
+ packet->data + 240, packet->data_len - 240,
+ &options) < 0) {
+ return -1;
+ }
+
+ if (options) {
+ pairinsert(&cursor, options);
+ }
}
/*
maxms->vp_integer = mtu->vp_integer;
}
- if (fr_debug_flag > 0) {
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
- /* Print debug output here? */
- }
- }
-
if (fr_debug_flag) fflush(stdout);
return 0;
int length;
unsigned int attribute;
uint8_t *ptr;
+ vp_cursor_t cursor;
VALUE_PAIR *vp, *tlv;
attribute = vps->da->attr & 0xffff00ff;
if (!tlv) return NULL;
tlv->length = 0;
- for (vp = vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &vps);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* Group the attributes ONLY until we see a
* non-TLV attribute.
}
ptr = tlv->vp_tlv;
- for (vp = vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &vps);
+ vp;
+ vp = pairnext(&cursor)) {
if (!vp->da->flags.is_tlv ||
vp->da->flags.extended ||
((vp->da->attr & 0xffff00ff) != attribute)) {
{
unsigned int i, num_vps;
uint8_t *p;
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
uint32_t lvalue, mms;
size_t dhcp_size, length;
* the later code.
*/
num_vps = 0;
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
num_vps++;
}
if (num_vps > 1) {
- VALUE_PAIR **array, **last;
+ VALUE_PAIR **array;
array = talloc_array(packet, VALUE_PAIR*, num_vps);
i = 0;
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
array[i++] = vp;
}
/*
* Sort the attributes.
*/
- qsort(array, (size_t) num_vps, sizeof(VALUE_PAIR *),
- attr_cmp);
+ qsort(array, (size_t) num_vps, sizeof(VALUE_PAIR *), attr_cmp);
- last = &packet->vps;
+ paircursor(&cursor, &packet->vps);
for (i = 0; i < num_vps; i++) {
- *last = array[i];
- array[i]->next = NULL;
- last = &(array[i]->next);
+ pairinsert(&cursor, array[i]->next);
}
talloc_free(array);
}
length = vp->length;
- for (same = vp->next; same != NULL; same = same->next) {
+ for (same = paircursor(&cursor, &vp->next);
+ same;
+ same = pairnext(&cursor)) {
if (same->da->attr != vp->da->attr) break;
num_entries++;
}
static int request_init(char const *filename)
{
FILE *fp;
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
int filedone = 0;
/*
* Fix / set various options
*/
- for (vp = request->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->vps); vp; vp = pairnext(&cursor)) {
switch (vp->da->attr) {
default:
break;
static size_t dhcp_options_xlat(UNUSED void *instance, REQUEST *request,
char const *fmt, char *out, size_t freespace)
{
- VALUE_PAIR *vp, *head = NULL, *next;
+ vp_cursor_t cursor;
+ VALUE_PAIR *vp, *head = NULL;
int decoded = 0;
while (isspace((int) *fmt)) fmt++;
goto fail;
}
- next = head;
-
- do {
- next = next->next;
- decoded++;
- } while (next);
-
+
+ for (vp = paircursor(&cursor, &head);
+ vp;
+ vp = pairnext(&cursor)) {
+ decoded++;
+ }
+
pairmove(request->packet, &(request->packet->vps), &head);
/* Free any unmoved pairs */
{
uint8_t *ptr, *end;
int attribute, length;
- VALUE_PAIR *vp, **tail;
+ vp_cursor_t cursor;
+ VALUE_PAIR *vp;
if (!packet || !packet->data) return -1;
if (packet->data_len < VQP_HDR_LEN) return -1;
- tail = &packet->vps;
-
+ paircursor(&cursor, &packet->vps);
vp = paircreate(packet, PW_VQP_PACKET_TYPE, 0);
if (!vp) {
fr_strerror_printf("No memory");
}
vp->vp_integer = packet->data[1];
debug_pair(vp);
-
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
vp = paircreate(packet, PW_VQP_ERROR_CODE, 0);
if (!vp) {
}
vp->vp_integer = packet->data[2];
debug_pair(vp);
-
- *tail = vp;
- tail = &(vp->next);
-
+ pairinsert(&cursor, vp);
+
vp = paircreate(packet, PW_VQP_SEQUENCE_NUMBER, 0);
if (!vp) {
fr_strerror_printf("No memory");
}
vp->vp_integer = packet->id; /* already set by vqp_recv */
debug_pair(vp);
-
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
ptr = packet->data + VQP_HDR_LEN;
end = packet->data + packet->data_len;
}
ptr += length;
debug_pair(vp);
-
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&cursor, vp);
}
/*
static int attr_filter_getfile(TALLOC_CTX *ctx, char const *filename, PAIR_LIST **pair_list)
{
+ vp_cursor_t cursor;
int rcode;
PAIR_LIST *attrs = NULL;
PAIR_LIST *entry;
entry = attrs;
while (entry) {
-
entry->check = entry->reply;
entry->reply = NULL;
- for (vp = entry->check; vp != NULL; vp = vp->next) {
-
+ for (vp = paircursor(&cursor, &entry->check);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* If it's NOT a vendor attribute,
* and it's NOT a wire protocol
/*
* Common attr_filter checks
*/
-static rlm_rcode_t attr_filter_common(void *instance, REQUEST *request,
- RADIUS_PACKET *packet)
+static rlm_rcode_t attr_filter_common(void *instance, REQUEST *request, RADIUS_PACKET *packet)
{
rlm_attr_filter_t *inst = instance;
+ vp_cursor_t cursor;
+ vp_cursor_t out;
VALUE_PAIR *vp;
- VALUE_PAIR *output;
- VALUE_PAIR **output_tail;
+ VALUE_PAIR *output, *input;
VALUE_PAIR *check_item;
PAIR_LIST *pl;
int found = 0;
int pass, fail = 0;
char const *keyname = NULL;
- VALUE_PAIR **input;
char buffer[256];
if (!packet) return RLM_MODULE_NOOP;
- input = &(packet->vps);
-
if (!inst->key) {
VALUE_PAIR *namepair;
keyname = buffer;
}
+ /*
+ * Head of the output list
+ */
output = NULL;
- output_tail = &output;
+ paircursor(&out, &output);
/*
* Find the attr_filter profile entry for the entry.
continue;
}
- RDEBUG2("Matched entry %s at line %d", pl->name,
- pl->lineno);
+ RDEBUG2("Matched entry %s at line %d", pl->name, pl->lineno);
found = 1;
- for (check_item = pl->check;
- check_item != NULL;
- check_item = check_item->next) {
+ for (check_item = paircursor(&cursor, &pl->check);
+ check_item;
+ check_item = pairnext(&cursor)) {
if (!check_item->da->vendor &&
(check_item->da->attr == PW_FALL_THROUGH) &&
(check_item->vp_integer == 1)) {
if (check_item->op == T_OP_SET ) {
vp = paircopyvp(packet, check_item);
if (!vp) {
- pairfree(&output);
- return RLM_MODULE_FAIL;
+ goto error;
}
- radius_xlat_move(request, output_tail, &vp);
- output_tail = &((*output_tail)->next);
+ radius_xlat_do(request, vp);
+ pairinsert(&out, vp);
}
}
* only if it matches all rules that describe an
* Idle-Timeout.
*/
- for (vp = *input; vp != NULL; vp = vp->next ) {
+ for (input = paircursor(&cursor, &packet->vps);
+ input;
+ input = pairnext(&cursor)) {
/* reset the pass,fail vars for each reply item */
pass = fail = 0;
* reset the check_item pointer to
* beginning of the list
*/
- for (check_item = pl->check;
- check_item != NULL;
- check_item = check_item->next) {
+ for (check_item = pairfirst(&cursor);
+ check_item;
+ check_item = pairnext(&cursor)) {
/*
* Vendor-Specific is special, and
* matches any VSA if the comparison
* is always true.
*/
- if ((check_item->da->attr == PW_VENDOR_SPECIFIC) &&
- (vp->da->vendor != 0) &&
- (check_item->op == T_OP_CMP_TRUE)) {
+ if ((check_item->da->attr == PW_VENDOR_SPECIFIC) && (input->da->vendor != 0) &&
+ (check_item->op == T_OP_CMP_TRUE)) {
pass++;
continue;
}
if (vp->da->attr == check_item->da->attr) {
- check_pair(check_item, vp,
- &pass, &fail);
+ check_pair(check_item, input, &pass, &fail);
}
}
if (!pass) {
RDEBUG3("Attribute (%s) allowed by relaxed mode", vp->da->name);
}
- *output_tail = paircopyvp(packet, vp);
- if (!*output_tail) {
- pairfree(&output);
- return RLM_MODULE_FAIL;
+ vp = paircopyvp(packet, vp);
+ if (!vp) {
+ goto error;
}
- output_tail = &((*output_tail)->next);
+ pairinsert(&out, vp);
}
}
/* If we shouldn't fall through, break */
- if (!fall_through)
+ if (!fall_through) {
break;
+ }
}
/*
return RLM_MODULE_NOOP;
}
- pairfree(input);
- *input = output;
+ /*
+ * Replace the existing request list with our filtered one
+ */
+ pairfree(&packet->vps);
+ packet->vps = output;
if (request->packet->code == PW_AUTHENTICATION_REQUEST) {
request->username = pairfind(request->packet->vps, PW_STRIPPED_USER_NAME, 0, TAG_ANY);
}
return RLM_MODULE_UPDATED;
+
+ error:
+ pairfree(&output);
+ return RLM_MODULE_FAIL;
}
#define RLM_AF_FUNC(_x, _y) static rlm_rcode_t mod_##_x(void *instance, REQUEST *request) \
break;
case T_OP_ADD:
- do {
- vp = map->dst->type == VPT_TYPE_LIST ?
- paircopyvp(c, found) :
- paircopyvpdata(c, map->dst->da,
- found);
- if (!vp) continue;
+ {
+ vp_cursor_t cursor;
- vp->op = map->op;
- pairadd(to_cache, vp);
+ for (found = paircursor(&cursor, &found);
+ found;
+ found = pairfindnext(&cursor, da->attr, da->vendor, TAG_ANY)) {
+ vp = map->dst->type == VPT_TYPE_LIST ?
+ paircopyvp(c, found) :
+ paircopyvpdata(c, map->dst->da, found);
+ if (!vp) continue;
- if (to_req) {
- vp = paircopyvp(request, vp);
- radius_pairmove(request, to_req,
- vp);
-
- }
+ vp->op = map->op;
+ pairadd(to_cache, vp);
- found = pairfind(found->next,
- da->attr,
- da->vendor,
- TAG_ANY);
- } while (found);
+ if (to_req) {
+ vp = paircopyvp(request, vp);
+ radius_pairmove(request, to_req, vp);
- break;
+ }
+ }
+ break;
+ }
default:
rad_assert(0);
}
break;
case VPT_TYPE_LIST:
- rad_assert(map->src->type == VPT_TYPE_LIST);
+ {
+ vp_cursor_t cursor;
+ VALUE_PAIR *i;
+
+ rad_assert(map->src->type == VPT_TYPE_LIST);
- from = NULL;
- context = request;
- if (radius_request(&context, map->src->request) == 0) {
- from = radius_list(context, map->src->list);
- }
- if (!from) continue;
+ from = NULL;
+ context = request;
+ if (radius_request(&context, map->src->request) == 0) {
+ from = radius_list(context, map->src->list);
+ }
+ if (!from) continue;
- found = paircopy(c, *from);
- if (!found) continue;
+ found = paircopy(c, *from);
+ if (!found) continue;
- for (vp = found; vp != NULL; vp = vp->next) {
- RDEBUG("\t%s %s %s (%s)", map->dst->name,
- fr_int2str(fr_tokens, map->op,
- "¿unknown?"),
- map->src->name,
- vp->da->name);
- vp->op = map->op;
- }
+ for (i = paircursor(&cursor, &vp);
+ i != NULL;
+ i = pairnext(&cursor)) {
+ RDEBUG("\t%s %s %s (%s)", map->dst->name,
+ fr_int2str(fr_tokens, map->op, "¿unknown?"),
+ map->src->name, i->da->name);
+ i->op = map->op;
+ }
- pairadd(to_cache, found);
+ pairadd(to_cache, found);
- if (to_req) {
- vp = paircopy(request, found);
- radius_pairmove(request, to_req, vp);
- }
+ if (to_req) {
+ vp = paircopy(request, found);
+ radius_pairmove(request, to_req, vp);
+ }
- break;
+ break;
+ }
/*
* It was most likely a double quoted string that now
* needs to be expanded.
vp_print(fp, &dst_vp);
}
- /* Write each attribute/value to the log file */
- for (vp = packet->vps; vp != NULL; vp = vp->next) {
- if (inst->ht &&
- fr_hash_table_finddata(inst->ht, &vp->da)) continue;
+ {
+ vp_cursor_t cursor;
+ /* Write each attribute/value to the log file */
+ for (vp = paircursor(&cursor, &packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
+ if (inst->ht &&
+ fr_hash_table_finddata(inst->ht, &vp->da)) continue;
- /*
- * Don't print passwords in old format...
- */
- if (compat && !vp->da->vendor && (vp->da->attr == PW_USER_PASSWORD)) continue;
+ /*
+ * Don't print passwords in old format...
+ */
+ if (compat && !vp->da->vendor && (vp->da->attr == PW_USER_PASSWORD)) continue;
- /*
- * Print all of the attributes.
- */
- vp_print(fp, vp);
+ /*
+ * Print all of the attributes.
+ */
+ vp_print(fp, vp);
+ }
}
/*
static int digest_fix(REQUEST *request)
{
- VALUE_PAIR *vp;
-
+ VALUE_PAIR *first, *i;
+ vp_cursor_t cursor;
+
/*
* We need both of these attributes to do the authentication.
*/
- vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE, 0, TAG_ANY);
- if (!vp) {
+ first = pairfind(request->packet->vps, PW_DIGEST_RESPONSE, 0, TAG_ANY);
+ if (!first) {
return RLM_MODULE_NOOP;
}
/*
* Check the sanity of the attribute.
*/
- if (vp->length != 32) {
- return RLM_MODULE_NOOP;
- }
-
- /*
- * We need these, too.
- */
- vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY);
- if (!vp) {
+ if (first->length != 32) {
return RLM_MODULE_NOOP;
}
* Check for proper format of the Digest-Attributes
*/
RDEBUG("Checking for correctly formatted Digest-Attributes");
- while (vp) {
- int length = vp->length;
+
+ first = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY);
+ if (!first) {
+ return RLM_MODULE_NOOP;
+ }
+
+ paircursor(&cursor, &first);
+ while ((i = pairfindnext(&cursor, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY))) {
+ int length = i->length;
int attrlen;
- uint8_t const *p = vp->vp_octets;
+ uint8_t const *p = i->vp_octets;
/*
* Until this stupidly encoded attribute is exhausted.
length -= attrlen;
p += attrlen;
} /* loop over this one attribute */
-
- /*
- * Find the next one, if it exists.
- */
- vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY);
}
/*
* Convert them to something sane.
*/
- RDEBUG("Digest-Attributes look OK. Converting them to something more usful.");
- vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY);
- while (vp) {
- int length = vp->length;
+ RDEBUG("Digest-Attributes look OK. Converting them to something more useful.");
+ pairfirst(&cursor);
+ while ((i = pairfindnext(&cursor, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY))) {
+ int length = i->length;
int attrlen;
- uint8_t const *p = vp->vp_octets;
+ uint8_t const *p = &i->vp_octets[0];
char *q;
VALUE_PAIR *sub;
length -= attrlen;
p += attrlen;
} /* loop over this one attribute */
-
- /*
- * Find the next one, if it exists.
- */
- vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES, 0, TAG_ANY);
}
return RLM_MODULE_OK;
* correctly
*/
RDEBUG2("Broken NAS did not set User-Name, setting from EAP Identity");
- vp = pairmake(request->packet, NULL, "User-Name", handler->identity, T_OP_EQ);
+ vp = pairmake(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
if (!vp) {
goto error;
}
- vp->next = request->packet->vps;
- request->packet->vps = vp;
-
} else {
/*
* A little more paranoia. If the NAS
* correctly
*/
RWDEBUG2("NAS did not set User-Name. Setting it locally from EAP Identity");
- vp = pairmake(request->packet, NULL, "User-Name", handler->identity, T_OP_EQ);
+ vp = pairmake(request->packet, &request->packet->vps, "User-Name", handler->identity, T_OP_EQ);
if (!vp) {
goto error2;
}
- vp->next = request->packet->vps;
- request->packet->vps = vp;
} else {
/*
* Paranoia. If the NAS *did* set the
int total, size;
const uint8_t *ptr;
VALUE_PAIR *head = NULL;
- VALUE_PAIR **tail = &head;
VALUE_PAIR *vp;
+ vp_cursor_t out;
total = eap->length[0] * 256 + eap->length[1];
ptr = (uint8_t const *) eap;
+ paircursor(&out, &head);
do {
size = total;
if (size > 253) size = 253;
}
pairmemcpy(vp, ptr, size);
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&out, vp);
ptr += size;
total -= size;
*/
eap_packet_raw_t *eap_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps)
{
- VALUE_PAIR *first, *vp;
+ VALUE_PAIR *first, *i;
eap_packet_raw_t *eap_packet;
unsigned char *ptr;
uint16_t len;
int total_len;
+ vp_cursor_t cursor;
/*
* Get only EAP-Message attribute list
* Sanity check the length, BEFORE allocating memory.
*/
total_len = 0;
- for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0, TAG_ANY)) {
- total_len += vp->length;
+ paircursor(&cursor, &first);
+ while ((i = pairfindnext(&cursor, PW_EAP_MESSAGE, 0, TAG_ANY))) {
+ total_len += i->length;
if (total_len > len) {
DEBUG("rlm_eap: Malformed EAP packet. Length in packet header does not match actual length");
ptr = (unsigned char *)eap_packet;
/* RADIUS ensures order of attrs, so just concatenate all */
- for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE, 0, TAG_ANY)) {
- memcpy(ptr, vp->vp_strvalue, vp->length);
- ptr += vp->length;
+ pairfirst(&cursor);
+ while ((i = pairfindnext(&cursor, PW_EAP_MESSAGE, 0, TAG_ANY))) {
+ memcpy(ptr, i->vp_strvalue, i->length);
+ ptr += i->length;
}
return eap_packet;
uint8_t const *append;
int appendlen;
unsigned char subtype;
+ vp_cursor_t cursor;
macspace = NULL;
append = NULL;
* that we need to encode all of this.
*/
encoded_size = 0;
- for (vp = r->vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &r->vps);
+ vp;
+ vp = pairnext(&cursor)) {
int roundedlen;
int vplen;
* SIM code adds a subtype, and 2 bytes of reserved = 3.
*
*/
-
-
encoded_size += 3;
encodedmsg = talloc_array(ep, uint8_t, encoded_size);
if (!encodedmsg) {
*/
attr = encodedmsg+3;
- for(vp = r->vps; vp != NULL; vp = vp->next) {
+ for (vp = pairfirst(&cursor); vp; vp = pairnext(&cursor)) {
int roundedlen;
if(vp->da->attr < ATTRIBUTE_EAP_SIM_BASE ||
char *p;
VALUE_PAIR *vp;
eap_handler_t *handler;
+ vp_cursor_t cursor;
/*
* Just in case the admin lists EAP in post-proxy-type Fail.
* There may be more than one Cisco-AVPair.
* Ensure we find the one with the LEAP attribute.
*/
- vp = request->proxy_reply->vps;
+ paircursor(&cursor, &request->proxy_reply->vps);
for (;;) {
/*
* Hmm... there's got to be a better way to
* This is vendor Cisco (9), Cisco-AVPair
* attribute (1)
*/
- vp = pairfind(vp, 1, 9, TAG_ANY);
+ vp = pairfindnext(&cursor, 1, 9, TAG_ANY);
if (!vp) {
return RLM_MODULE_NOOP;
}
if (strncasecmp(vp->vp_strvalue, "leap:session-key=", 17) == 0) {
break;
}
-
- /*
- * Not this AV-pair. Go to the next one.
- */
- vp = vp->next;
}
/*
{
size_t total;
uint8_t *p;
- VALUE_PAIR *vp = NULL, *head, **tail;
+ VALUE_PAIR *vp = NULL, *head = NULL;
+ vp_cursor_t cursor;
if (data_len > 65535) return NULL; /* paranoia */
memcpy(p + EAP_HEADER_LEN, data, total);
- head = vp;
- tail = &(vp->next);
+ paircursor(&cursor, &head);
+ pairinsert(&cursor, vp);
while (total < data_len) {
vp = paircreate(packet, PW_EAP_MESSAGE, 0);
if (!vp) {
pairmemcpy(vp, data + total, (data_len - total));
total += vp->length;
- *tail = vp;
- tail = &(vp->next);
+
+ pairinsert(&cursor, vp);
}
return head;
static int vp2eap(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *vp)
{
rad_assert(vp != NULL);
+ VALUE_PAIR *this;
+ vp_cursor_t cursor;
/*
* Skip the id, code, and length. Just write the EAP
*/
#ifndef NDEBUG
if ((debug_flag > 2) && fr_log_fp) {
- size_t i, total;
- VALUE_PAIR *this;
-
+ size_t i, total, start = EAP_HEADER_LEN;
total = 0;
- for (this = vp; this != NULL; this = this->next) {
- int start = 0;
-
- if (this == vp) start = EAP_HEADER_LEN;
-
+ for (this = paircursor(&cursor, &vp); this; this = pairnext(&cursor)) {
for (i = start; i < vp->length; i++) {
- if ((total & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data out %04x: ", (int) total);
-
+ if ((total & 0x0f) == 0) {
+ fprintf(fr_log_fp, " PEAP tunnel data out %04x: ", (int) total);
+ }
fprintf(fr_log_fp, "%02x ", vp->vp_octets[i]);
- if ((total & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
+ if ((total & 0x0f) == 0x0f) {
+ fprintf(fr_log_fp, "\n");
+ }
+
total++;
}
+
+ start = 0;
+ }
+
+ if ((total & 0x0f) != 0) {
+ fprintf(fr_log_fp, "\n");
}
- if ((total & 0x0f) != 0) fprintf(fr_log_fp, "\n");
}
#endif
/*
* Send the EAP data, WITHOUT the header.
*/
- (tls_session->record_plus)(&tls_session->clean_in,
- vp->vp_octets + EAP_HEADER_LEN,
- vp->length - EAP_HEADER_LEN);
+ (tls_session->record_plus)(&tls_session->clean_in, vp->vp_octets + EAP_HEADER_LEN, vp->length - EAP_HEADER_LEN);
/*
* Send the rest of the EAP data.
*/
- for (vp = vp->next; vp != NULL; vp = vp->next) {
- (tls_session->record_plus)(&tls_session->clean_in,
- vp->vp_octets, vp->length);
+ for (this = paircursor(&cursor, &vp);
+ this;
+ this = pairnext(&cursor)) {
+ (tls_session->record_plus)(&tls_session->clean_in, this->vp_octets, this->length);
}
tls_handshake_send(request, tls_session);
*/
if (t->copy_request_to_tunnel) {
VALUE_PAIR *copy;
+ vp_cursor_t cursor;
- for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
/*
* The attribute is a server-side thingy,
* don't copy it.
*/
- if ((vp->da->attr > 255) &&
- (((vp->da->attr >> 16) & 0xffff) == 0)) {
+ if ((vp->da->attr > 255) && (((vp->da->attr >> 16) & 0xffff) == 0)) {
continue;
}
size_t size;
size_t data_left = data_len;
char *p;
- VALUE_PAIR *first = NULL;
- VALUE_PAIR **last = &first;
+ VALUE_PAIR *first;
VALUE_PAIR *vp;
RADIUS_PACKET *packet = fake->packet; /* FIXME: api issues */
-
+ vp_cursor_t out;
+
+ paircursor(&out, &first);
+
while (data_left > 0) {
rad_assert(data_left <= data_len);
memcpy(&attr, data, sizeof(attr));
* Normal attributes cannot be.
*/
if ((attr > 255) && (vendor == 0)) {
- RWDEBUG2("Skipping Diameter attribute %u",
- attr);
+ RWDEBUG2("Skipping Diameter attribute %u", attr);
goto next_attr;
}
goto do_octets;
}
- *last = vp;
- do {
- last = &(vp->next);
- vp = vp->next;
- } while (vp != NULL);
+ pairinsert(&out, vp);
goto next_attr;
}
/*
* Update the list.
*/
- *last = vp;
- last = &(vp->next);
+ pairinsert(&out, vp);
next_attr:
/*
size_t total;
uint64_t attr64;
VALUE_PAIR *vp;
+ vp_cursor_t cursor;
p = buffer;
total = 0;
- for (vp = first; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &first); vp; vp = pairnext(&cursor)) {
/*
* Too much data: die.
*/
*/
if (t->copy_request_to_tunnel) {
VALUE_PAIR *copy;
-
- for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+ vp_cursor_t cursor;
+
+ for (vp = paircursor(&cursor, &request->packet->vps); vp; vp = pairnext(&cursor)) {
/*
* The attribute is a server-side thingy,
* don't copy it.
entry = users;
while (entry) {
+ vp_cursor_t cursor;
if (compat_mode) {
DEBUG("[%s]:%d Cistron compatibility checks for entry %s ...",
filename, entry->lineno,
* and probably ':=' for server
* configuration items.
*/
- for (vp = entry->check; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &entry->check); vp; vp = pairnext(&cursor)) {
/*
* Ignore attributes which are set
* properly.
* It's a common enough mistake, that it's
* worth doing.
*/
- for (vp = entry->reply; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &entry->reply); vp; vp = pairnext(&cursor)) {
/*
* If it's NOT a vendor attribute,
* and it's NOT a wire protocol
static VALUE_PAIR *rlm_ldap_map_getvalue(REQUEST *request, value_pair_map_t const *map, void *ctx)
{
rlm_ldap_result_t *self = ctx;
- VALUE_PAIR *head, **tail, *vp;
+ VALUE_PAIR *head = NULL, *vp;
+ vp_cursor_t out;
int i;
- head = NULL;
- tail = &head;
+ paircursor(&out, &head);
/*
* Iterate over all the retrieved values,
}
vp->op = map->op;
- *tail = vp;
- tail = &(vp->next);
+ pairinsert(&out, vp);
}
return head;
{
VALUE_PAIR *vp;
int ret;
+ vp_cursor_t cursor;
- vp = request->config_items;
- while ((vp = pairfind(vp, inst->group_da->attr, inst->group_da->vendor, TAG_ANY))) {
+ paircursor(&cursor, &request->config_items);
+ while ((vp = pairfindnext(&cursor, inst->group_da->attr, inst->group_da->vendor, TAG_ANY))) {
ret = radius_compare_vps(request, check, vp);
if (ret == 0) {
RDEBUG2("User found. Matched cached membership");
if (ret < 0) {
return RLM_MODULE_FAIL;
}
- vp = vp->next;
}
RDEBUG2("Membership not found");
* 06:<mschapid>:00:02:<2nd chunk>
* 06:<mschapid>:00:03:<3rd chunk>
*/
- for (seq=1;seq<4;seq++) {
- int found=0;
- for (nt_enc=request->packet->vps; nt_enc; nt_enc=nt_enc->next) {
+ for (seq = 1; seq < 4; seq++) {
+ vp_cursor_t cursor;
+ int found = 0;
+
+ for (nt_enc = paircursor(&cursor, &request->packet->vps);
+ nt_enc;
+ nt_enc = pairnext(&cursor)) {
if (nt_enc->da->vendor != VENDORPEC_MICROSOFT)
continue;
rlm_pap_t *inst = instance;
int auth_type = false;
int found_pw = false;
- VALUE_PAIR *vp, *next;
-
- for (vp = request->config_items; vp != NULL; vp = next) {
- next = vp->next;
-
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
+
+ for (vp = paircursor(&cursor, &request->config_items);
+ vp;
+ vp = pairnext(&cursor)) {
switch (vp->da->attr) {
case PW_USER_PASSWORD: /* deprecated */
RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
{
VALUE_PAIR *vp;
rlm_rcode_t rc = RLM_MODULE_INVALID;
+ vp_cursor_t cursor;
int (*auth_func)(REQUEST *, VALUE_PAIR *) = NULL;
+
if (!request->password ||
(request->password->da->attr != PW_USER_PASSWORD)) {
* config items, to find out which authentication
* function to call.
*/
- for (vp = request->config_items; vp != NULL; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->config_items);
+ vp;
+ vp = pairnext(&cursor)) {
if (!vp->da->vendor) switch (vp->da->attr) {
case PW_CLEARTEXT_PASSWORD:
auth_func = &pap_auth_clear;
buffer[strlen(buffer)-1] = 0;
pw = get_pw_nam(buffer, ht, &last_found);
printpw(pw,4);
- while (pw = get_next(buffer, ht, &last_found)) printpw(pw,4);
+ while ((pw = get_next(buffer, ht, &last_found))) printpw(pw,4);
}
release_ht(ht);
}
{
#define inst ((struct passwd_instance *)instance)
char buffer[1024];
- VALUE_PAIR * key;
+ VALUE_PAIR *key, *i;
struct mypasswd * pw, *last_found;
- int found = 0;
+ vp_cursor_t cursor;
- for (key = request->packet->vps;
- key && (key = pairfind(key, inst->keyattr->attr, inst->keyattr->vendor, TAG_ANY));
- key = key->next ){
+ key = pairfind(request->packet->vps, inst->keyattr->attr, inst->keyattr->vendor, TAG_ANY);
+ if (!key) {
+ return RLM_MODULE_NOTFOUND;
+ }
+
+ for (i = paircursor(&cursor, &key);
+ i;
+ i = pairfindnext(&cursor, inst->keyattr->attr, inst->keyattr->vendor, TAG_ANY)){
/*
* Ensure we have the string form of the attribute
*/
- vp_prints_value(buffer, sizeof(buffer), key, 0);
- if (! (pw = get_pw_nam(buffer, inst->ht, &last_found)) ) {
+ vp_prints_value(buffer, sizeof(buffer), i, 0);
+ if (!(pw = get_pw_nam(buffer, inst->ht, &last_found)) ) {
continue;
}
do {
addresult(inst, request, request, &request->config_items, pw, 0, "config_items");
addresult(inst, request, request->reply, &request->reply->vps, pw, 1, "reply_items");
- addresult(inst, request, request->packet, &request->packet->vps, pw, 2, "request_items");
- } while ( (pw = get_next(buffer, inst->ht, &last_found)) );
- found++;
- if (!inst->allowmultiple) break;
- }
- if(!found) {
- return RLM_MODULE_NOTFOUND;
+ addresult(inst, request, request->packet, &request->packet->vps, pw, 2, "request_items");
+ } while ((pw = get_next(buffer, inst->ht, &last_found)));
+
+ if (!inst->allowmultiple) {
+ break;
+ }
}
+
return RLM_MODULE_OK;
#undef inst
head = paircopy(ctx, vps);
while (head) {
+ vp_cursor_t cursor;
/*
* Tagged attributes are added to the hash with name
* <attribute>:<tag>, others just use the normal attribute
sublist = NULL;
pairfilter(ctx, &sublist, &head, head->da->attr, head->da->vendor, head->tag);
+ paircursor(&cursor, &sublist);
/*
* Attribute has multiple values
*/
- if (sublist->next) {
+ if (pairnext(&cursor)) {
VALUE_PAIR *vp;
av = newAV();
- for (vp = sublist; vp; vp = vp->next) {
+ for (vp = pairfirst(&cursor);
+ vp;
+ vp = pairnext(&cursor)) {
len = vp_prints_value(buffer, sizeof(buffer), vp, false);
av_push(av, newSVpv(buffer, len));
}
char *ptr;
char newattr[MAX_STRING_LEN];
VALUE_PAIR *vp;
-
- for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+ vp_cursor_t cursor;
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
vendorcode = vp->da->vendor;
if (!((vendorcode == 9) || (vendorcode == 6618))) {
continue; /* not a Cisco or Quintum VSA, continue */
static void alvarion_vsa_hack(VALUE_PAIR *vp)
{
int number = 1;
-
- for ( ; vp != NULL; vp = vp->next) {
+ vp_cursor_t cursor;
+
+ for (vp = paircursor(&cursor, &vp);
+ vp;
+ vp = pairnext(&cursor)) {
const DICT_ATTR *da;
if (vp->da->vendor != 12394) {
VALUE_PAIR *namepair;
VALUE_PAIR *request_pairs;
VALUE_PAIR *tmp;
+ vp_cursor_t cursor;
/*
* Get the username from the request
}
num_proxy_state = 0;
- for (tmp = request->packet->vps; tmp != NULL; tmp = tmp->next) {
+ for (tmp = paircursor(&cursor, &request->packet->vps);
+ tmp;
+ tmp = pairnext(&cursor)) {
if (tmp->da->vendor != 0) {
continue;
}
*/
static int hunt_paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check)
{
- VALUE_PAIR *check_item = check;
+ vp_cursor_t cursor;
+ VALUE_PAIR *check_item;
VALUE_PAIR *tmp;
int result = -1;
if (!check) return 0;
- while (result != 0 && check_item != NULL) {
-
- tmp = check_item->next;
- check_item->next = NULL;
-
+ for (check_item = paircursor(&cursor, check);
+ check_item && (result != 0);
+ check_item = pairnext(&cursor)) {
+ /* FIXME: paircopy should be removed once VALUE_PAIRs are no longer in linked lists */
+ tmp = paircopyvp(request, check_item);
result = paircompare(req, request, check_item, NULL);
-
- check_item->next = tmp;
- check_item = check_item->next;
+ pairfree(&tmp);
}
return result;
static int do_python(REQUEST *request, PyObject *pFunc,
char const *funcname)
{
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
PyObject *pRet = NULL;
PyObject *pArgs = NULL;
*/
tuplelen = 0;
if (request != NULL) {
- for (vp = request->packet->vps; vp; vp = vp->next)
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
tuplelen++;
+ }
}
gstate = PyGILState_Ensure();
if ((pArgs = PyTuple_New(tuplelen)) == NULL)
goto failed;
- for (vp = request->packet->vps;
- vp != NULL;
- vp = vp->next, i++) {
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor), i++) {
PyObject *pPair;
/* The inside tuple has two only: */
{
rlm_rcode_t rcode = RLM_MODULE_OK;
struct radutmp ut, u;
+ vp_cursor_t cursor;
VALUE_PAIR *vp;
int status = -1;
int protocol = -1;
/*
* First, find the interesting attributes.
*/
- for (vp = request->packet->vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
if (!vp->da->vendor) switch (vp->da->attr) {
case PW_LOGIN_IP_HOST:
case PW_FRAMED_IP_ADDRESS:
pair_lists_t list, unsigned int code)
{
int rcode = RLM_MODULE_NOOP;
- VALUE_PAIR *vp, **vps, *last;
+ VALUE_PAIR *vp, **vps;
+ vp_cursor_t cursor;
home_server *home;
REALM *realm;
home_pool_t *pool;
RADIUS_PACKET *packet = NULL;
- last = request->config_items;
-
/*
* Send as many packets as necessary to different
* destinations.
*/
- while (1) {
- vp = pairfind(last, PW_REPLICATE_TO_REALM, 0, TAG_ANY);
- if (!vp) break;
-
- last = vp->next;
+ paircursor(&cursor, &request->config_items);
+ while ((vp = pairfindnext(&cursor, PW_REPLICATE_TO_REALM, 0, TAG_ANY))) {
realm = realm_find2(vp->vp_strvalue);
if (!realm) {
unsigned short count = 0, i;
unsigned short swap;
+ vp_cursor_t cursor;
VALUE_PAIR **current, *tmp;
/*
/*
* Create sorted array of VP pointers
*/
- tmp = request->packet->vps;
- while (tmp != NULL) {
- tmp = tmp->next;
+ for (tmp = paircursor(&cursor, &request->packet->vps);
+ tmp;
+ tmp = pairnext(&cursor)) {
count++;
}
ctx->first = current = rad_malloc((sizeof(tmp) * (count + 1)));
ctx->next = ctx->first;
+
+ current[0] = NULL;
- tmp = request->packet->vps;
- while (tmp != NULL) {
- *current++ = tmp;
- tmp = tmp->next;
+ for (tmp = paircursor(&cursor, &request->packet->vps);
+ tmp;
+ tmp = pairnext(&cursor)) {
+ *current++ = tmp;
}
- current[0] = NULL;
+
current = ctx->first;
if (!sort || (count < 2)) return;
#define BUF_SIZE 1024
static rlm_rcode_t do_ruby(REQUEST *request, unsigned long func,
VALUE module, char const *function_name) {
-
rlm_rcode_t rcode = RLM_MODULE_OK;
+ vp_cursor_t cursor;
char buf[BUF_SIZE]; /* same size as vp_print buffer */
n_tuple = 0;
if (request) {
- for (vp = request->packet->vps; vp; vp = vp->next) {
- n_tuple++;
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
+ n_tuple++;
}
}
*/
rb_request = rb_ary_new2(n_tuple);
if (request) {
- for (vp = request->packet->vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
VALUE tmp = rb_ary_new2(2);
/* The name. logic from vp_prints, lib/print.c */
static rlm_rcode_t mod_accounting(void *instance, REQUEST *request)
{
VALUE_PAIR *vp;
+ vp_cursor_t cursor;
FILE *fp;
struct utmp ut;
time_t t;
/*
* First, find the interesting attributes.
*/
- for (vp = request->packet->vps; vp; vp = vp->next) {
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
if (!vp->da->vendor) switch (vp->da->attr) {
case PW_USER_NAME:
if (vp->length >= sizeof(ut.ut_name)) {
static rlm_rcode_t utf8_clean(UNUSED void *instance, REQUEST *request)
{
size_t i, len;
- VALUE_PAIR *vp, *next;
-
- for (vp = request->packet->vps; vp != NULL; vp = next) {
- next = vp->next;
+ VALUE_PAIR *vp;
+ vp_cursor_t cursor;
+ for (vp = paircursor(&cursor, &request->packet->vps);
+ vp;
+ vp = pairnext(&cursor)) {
if (vp->da->type != PW_TYPE_STRING) continue;
for (i = 0; i < vp->length; i += len) {