ARPA2 Common Libraries  2.2.25
Data Structures | Macros | Functions
Iteration of ARPA2 Selectors
Collaboration diagram for Iteration of ARPA2 Selectors:

Data Structures

struct  a2sel_quickiter
 Storage structure for Quick Iteration. More...
 

Macros

#define a2id_iterate_init(in, cursor)   a2sel_iterate_init ((const a2sel_t *) (start), (cursor))
 Start iterating over an ARPA2 Identity.
 
#define a2id_iterate_next(in, cursor)   a2sel_iterate_next ((const a2sel_t *) (start), (cursor))
 Progress to the next Iterator value.
 
#define a2sel_abstractions_domain(steps)   ((steps) >> 7)
 
#define a2sel_abstractions_username(steps)   ((steps) & 0x007f)
 

Functions

bool a2sel_iterate_init (const a2sel_t *start, a2sel_t *cursor)
 Iterate an ARPA2 Selector or ARPA2 Identity. More...
 
bool a2sel_iterate_next (const a2sel_t *start, a2sel_t *cursor)
 Progress to the next Iterator value.
 
bool a2sel_quickiter_init (a2sel_quickiter *iter)
 Lightweight / Lightning-fast ARPA2 Selector and Identity iteration. More...
 
bool a2sel_quickiter_next (a2sel_quickiter *iter)
 Iterate to the next Quick Iterator value.
 
bool a2sel_abstractions (const a2sel_t *specific, const a2sel_t *generic, uint16_t *steps)
 Count the number of abstractions to go from one ARPA2 Selector (or Identity) to another ARPA2 Selector. More...
 

Detailed Description

Function Documentation

◆ a2sel_abstractions()

bool a2sel_abstractions ( const a2sel_t specific,
const a2sel_t generic,
uint16_t *  steps 
)

Count the number of abstractions to go from one ARPA2 Selector (or Identity) to another ARPA2 Selector.

This is done as fast as possible, and no other information is derived. The return value is false when it is impossible to make these steps, so it is another mechanism to test specialisation.

Counting is not linear; to ensure that username abstractions count as less influential, they are greatly outnumbered by domain name abstractions. You can exploit this to infer the number of abstraction steps for the domain and username, by passing a2sel_abstractions_domain() and _steps() over the steps output here.

The purpose of this function is to handle multiple matches, and learn which is the closest match. This can be practical when comparing an Access Rule, such as one loaded from LDAP or in an application that defines Access Rules in a static configuration.

On success, the function returns true. On failure, it returns false and sets errno to a com_err code. In either case, it sets steps to a value, but failure will set the highest possible value, which is unreachable in any other way.

◆ a2sel_iterate_init()

bool a2sel_iterate_init ( const a2sel_t start,
a2sel_t cursor 
)

Iterate an ARPA2 Selector or ARPA2 Identity.

This turns it into an ever more abstract structure, but the first bet is always the original structure.

Signatures are always removed during iteration. Just asking for presence of a signature adds nothing. And the signature flags are unsuitable for iteration because that would call for the (expensive) iteration over all possible subsets. You can use the a2id_match() and variants to set a lower bound on signatures.

Domains are iterated by removing one label at a time and starting with the dot after it. The final domain is "." or the most abstract one.

Users for which we rely on ARPA2 semantics can have aliases, so we can iterate by removing one of these in turns, but leaving the + that precedes it as an "open end". The last of the user patterns mentions just the user, and no user at all.

Services are always represented with their name, but the arguments may be stripped one by one, as for user aliases, and the + is left as an "open end" in that case too.

The outer loop of iteration (slow changes) are for domain abstraction. The inner loop (fast changes) are for user/service iteration. In every iteration, the most abstract form is the last and will be the "@." selector.

The iterated value is stored in the cursor, and updated on every _next invocation. The routines can be used like this (example for an a2id_t, but a2sel_t works the same):

 a2id_t me;
 a2sel_t crs;
 if (a2id_iterate_init (&me, &crs)) do {
    ...process (crs)...
 } while (a2id_iterate_next (&me, &crs));

◆ a2sel_quickiter_init()

bool a2sel_quickiter_init ( a2sel_quickiter iter)

Lightweight / Lightning-fast ARPA2 Selector and Identity iteration.

This uses a simple structure with a pointer to the userid and domain, with a length field for the former and NUL termination for the latter. This means that a little more work is done by the user, but there is less pressure on the iterator in terms of strings being copied and offsets of the a2sel_t being kept up to date.

This mechanism is perfect for fast implementations, and is specifically interesting for database lookups such as the ACL logic of <arpa2/access.h>.

You are supposed to fill the src value and ensure its stability througout iteration. The use is like:

 a2sel_quickiter qiter;
 qiter.src = ...ref...;
 if (a2sel_quickiter_init (&qiter)) do {
    ...printf ("%.*s@%s", qiter.uidlen, qiter.uid, qiter.dom)...
 } while (a2sel_quickiter_next (&qiter));