55#include <netinet/in.h>
57#include <radcli/radcli-defs.h>
80typedef struct rc_conf radcli_ctx;
93#define RADCLI_OPT_ENTRY(id, name, type) RADCLI_##id,
95#undef RADCLI_OPT_ENTRY
142 const void *identity,
size_t identity_len,
143 const uint8_t *key,
size_t keylen);
252struct radcli_attr_def_st;
253typedef struct radcli_attr_def_st radcli_attr_def;
268 const char *name, uint32_t *out);
287typedef struct radcli_avp_st radcli_avp;
294struct radcli_avp_list_st;
295typedef struct radcli_avp_list_st radcli_avp_list;
301int radcli_avp_add_bytes(radcli_avp_list *list,
const radcli_attr_def *def,
const void *value,
size_t len);
303int radcli_avp_add_str(radcli_avp_list *list,
const radcli_attr_def *def,
const char *value);
309int radcli_avp_add_ip4(radcli_avp_list *list,
const radcli_attr_def *def,
struct in_addr value);
312 const struct in6_addr *value,
unsigned prefix);
315 struct in_addr value,
unsigned prefix);
339 uint32_t attrid, uint32_t vendor,
340 const void *value,
size_t len);
343 uint32_t attrid, uint32_t vendor,
const char *value);
346 uint32_t attrid, uint32_t vendor, uint32_t value);
349 uint32_t attrid, uint32_t vendor, uint64_t value);
352 uint32_t attrid, uint32_t vendor,
struct in_addr value);
355 uint32_t attrid, uint32_t vendor,
356 const struct in6_addr *value,
unsigned prefix);
359 uint32_t attrid, uint32_t vendor,
360 struct in_addr value,
unsigned prefix);
365 const char *username,
const char *realm);
367const radcli_avp *
radcli_avp_get(
const radcli_avp_list *list,
const radcli_attr_def *def,
unsigned idx);
390 const radcli_avp_list *list;
391 const radcli_avp *cur;
430 uint32_t attrid, uint32_t vendor,
unsigned idx);
433 uint32_t attrid, uint32_t vendor, uint32_t *out);
436 uint32_t attrid, uint32_t vendor, uint64_t *out);
439 uint32_t attrid, uint32_t vendor,
440 struct in6_addr *out,
unsigned *prefix);
443 uint32_t attrid, uint32_t vendor,
444 struct in_addr *out,
unsigned *prefix);
447 uint32_t attrid, uint32_t vendor,
448 const void **out,
size_t *len);
451 uint32_t attrid, uint32_t vendor);
464 const radcli_attr_def *def,
const char *sep);
467 const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor,
475 const radcli_attr_def *octets, uint64_t value);
478 const radcli_attr_def *octets, uint64_t *out);
481 uint32_t attrid, uint32_t vendor, uint64_t value);
484 uint32_t attrid, uint32_t vendor, uint64_t *out);
507 RADCLI_CODE_ACCESS_REQUEST = 1,
508 RADCLI_CODE_ACCESS_ACCEPT = 2,
509 RADCLI_CODE_ACCESS_REJECT = 3,
510 RADCLI_CODE_ACCOUNTING_REQUEST = 4,
511 RADCLI_CODE_ACCOUNTING_RESPONSE = 5,
512 RADCLI_CODE_ACCESS_CHALLENGE = 11,
516 RADCLI_DISCONNECT_REQUEST = 40,
517 RADCLI_DISCONNECT_ACK = 41,
518 RADCLI_DISCONNECT_NAK = 42,
519 RADCLI_COA_REQUEST = 43,
532 RADCLI_ERROR_RESIDUAL_SESSION_CONTEXT_REMOVED = 201,
533 RADCLI_ERROR_INVALID_EAP_PACKET = 202,
534 RADCLI_ERROR_UNSUPPORTED_ATTRIBUTE = 401,
535 RADCLI_ERROR_MISSING_ATTRIBUTE = 402,
536 RADCLI_ERROR_NAS_IDENTIFICATION_MISMATCH = 403,
537 RADCLI_ERROR_INVALID_REQUEST = 404,
538 RADCLI_ERROR_UNSUPPORTED_SERVICE = 405,
539 RADCLI_ERROR_UNSUPPORTED_EXTENSION = 406,
540 RADCLI_ERROR_INVALID_ATTRIBUTE_VALUE = 407,
541 RADCLI_ERROR_ADMINISTRATIVELY_PROHIBITED = 501,
542 RADCLI_ERROR_REQUEST_NOT_ROUTABLE = 502,
543 RADCLI_ERROR_SESSION_CONTEXT_NOT_FOUND = 503,
544 RADCLI_ERROR_SESSION_CONTEXT_NOT_REMOVABLE = 504,
545 RADCLI_ERROR_OTHER_PROXY_PROCESSING_ERROR = 505,
546 RADCLI_ERROR_RESOURCES_UNAVAILABLE = 506,
547 RADCLI_ERROR_REQUEST_INITIATED = 507,
548 RADCLI_ERROR_MULTIPLE_SESSION_SELECTION_UNSUPPORTED = 508,
549 RADCLI_ERROR_LOCATION_INFO_REQUIRED = 509,
550 RADCLI_ERROR_RESPONSE_TOO_BIG = 601
579struct radcli_request_st;
580typedef struct radcli_request_st radcli_request;
584 RADCLI_REQUEST_NONE = 0,
626 radcli_code *out_code, radcli_avp_list **out_attrs);
722 void *buf,
size_t *len);
728#define RADCLI_DAE_NEW 0
733#define RADCLI_DAE_DUPLICATE 1
736 const struct sockaddr *from, socklen_t fromlen,
764#define RADCLI_CTX_MAX_POLLFDS 2
767 size_t *nfds,
int *timeout_ms);
int radcli_dae_req_nas_port(const radcli_dae_request *req, uint32_t *out)
Return the request's NAS-Port.
void radcli_dae_free(radcli_dae *dae)
Release a listener, closing its socket if radcli_dae_start() opened one.
const char * radcli_dae_req_session_id(const radcli_dae_request *req)
Return the request's Acct-Session-Id, if it carried one.
void(* radcli_dae_handler)(radcli_dae_request *req, void *user)
Application callback invoked by radcli_ctx_dispatch() for a validated request.
int radcli_ctx_get_poll(radcli_ctx *ctx, struct pollfd *pfds, size_t max_pfds, size_t *nfds, int *timeout_ms)
Report what to wait for on ctx's behalf, for the caller's own event loop – radcli never calls poll()/...
void radcli_dae_set_handler(radcli_dae *dae, radcli_dae_handler cb, void *user)
Register the callback radcli_ctx_dispatch() invokes for each validated request. May be called before ...
radcli_code radcli_dae_req_code(const radcli_dae_request *req)
Return the received packet's RADIUS code.
int radcli_ctx_dispatch(radcli_ctx *ctx)
Read what is ready on ctx's descriptor(s), validate it, and invoke the registered handler for anythin...
int radcli_dae_reply(radcli_dae_request *req, int ack)
Answer a request with an ACK or NAK, selecting 41/42 or 44/45 from the request's own code,...
struct radcli_dae_st radcli_dae
const char * radcli_dae_req_user_name(const radcli_dae_request *req)
Return the request's User-Name, if it carried one.
int radcli_dae_start(radcli_dae *dae)
Start receiving: binds the socket described by dae-listen.
const radcli_avp_list * radcli_dae_req_attrs(const radcli_dae_request *req)
Return the request's decoded attributes.
int radcli_dae_reply_to_buffer(radcli_dae_request *req, int ack, uint32_t error_cause, void *buf, size_t *len)
Produce a reply as bytes instead of sending it – the L0 counterpart of radcli_dae_reply()/radcli_dae_...
int radcli_dae_process(radcli_dae *dae, const void *buf, size_t len, const struct sockaddr *from, socklen_t fromlen, radcli_dae_request **req)
Validate a caller-supplied packet, without a radcli-owned socket – the L0 counterpart of radcli_ctx_d...
int radcli_dae_reply_error(radcli_dae_request *req, uint32_t error_cause)
Answer a request with a NAK carrying the given Error-Cause.
radcli_dae * radcli_dae_new(radcli_ctx *ctx, unsigned flags)
Validate dae-* configuration and build a dynamic-authorization listener. Opens no socket – see radcli...
int radcli_dae_req_framed_ip(const radcli_dae_request *req, struct sockaddr_storage *out)
Return the request's Framed-IP-Address or Framed-IPv6-Address.
struct radcli_dae_request_st radcli_dae_request
void radcli_dae_request_free(radcli_dae_request *req)
Release a request.
@ RADCLI_DAE_NO_NAS_CHECK
int radcli_avp_add_ip6_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, const struct in6_addr *value, unsigned prefix)
Look up an IPv6-address or IPv6-prefix-typed attribute by legacy numeric ID and append it.
int radcli_avp_add_uint32_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, uint32_t value)
Look up an integer/IPv4-address/date-typed attribute by legacy numeric ID and append it.
int radcli_avp_add_uint64_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, uint64_t value)
Look up a 64-bit integer-typed attribute by legacy numeric ID and append it.
int radcli_avp_add_bytes_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, const void *value, size_t len)
Look up an attribute by legacy numeric ID and append its bytes.
int radcli_avp_add_str_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, const char *value)
Look up a string-typed attribute by legacy numeric ID and append it.
int radcli_avp_add_ip4prefix_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, struct in_addr value, unsigned prefix)
Look up an IPv4-prefix-typed attribute by legacy numeric ID and append it.
int radcli_avp_add_ip4_by_num(radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, struct in_addr value)
Look up an IPv4-address-typed attribute by legacy numeric ID and append it.
int radcli_avp_concat_str(char *buf, size_t buflen, const radcli_avp_list *list, const radcli_attr_def *def, const char *sep)
Concatenate every occurrence of an attribute into a bounded buffer.
int radcli_avp_concat_str_by_num(char *buf, size_t buflen, const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, const char *sep)
Look up an attribute by legacy numeric ID and concatenate every occurrence into a bounded buffer.
int radcli_avp_get_uint64_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, uint64_t *out)
Look up a 64-bit integer-typed attribute by legacy numeric ID and read its first occurrence.
const radcli_avp * radcli_avp_get_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, unsigned idx)
Look up the idx-th occurrence of an attribute by legacy numeric ID.
int radcli_avp_get_ip4prefix_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, struct in_addr *out, unsigned *prefix)
Look up an IPv4-prefix-typed attribute by legacy numeric ID and read its first occurrence.
int radcli_avp_get_uint32_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, uint32_t *out)
Look up an integer/IPv4-address/date-typed attribute by legacy numeric ID and read its first occurren...
const char * radcli_avp_get_cstr_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor)
Look up an attribute by legacy numeric ID and read its first occurrence as a NUL-terminated string.
int radcli_avp_get_bytes_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, const void **out, size_t *len)
Look up an attribute by legacy numeric ID and read its first occurrence's raw bytes.
int radcli_avp_get_ip6_by_num(const radcli_avp_list *list, const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor, struct in6_addr *out, unsigned *prefix)
Look up an IPv6-address or IPv6-prefix-typed attribute by legacy numeric ID and read its first occurr...
int radcli_avp_add_ip4prefix(radcli_avp_list *list, const radcli_attr_def *def, struct in_addr value, unsigned prefix)
Append an IPv4-prefix-typed attribute.
int radcli_avp_get_uint64(const radcli_avp *a, uint64_t *out)
Read an attribute's value as a 64-bit integer or ifid.
int radcli_avp_add_username(radcli_avp_list *list, const radcli_ctx *ctx, const char *username, const char *realm)
Append a User-Name AVP, appending a realm as "username@realm" unless username already contains one.
int radcli_avp_get_gigawords64_by_num(const radcli_ctx *ctx, const radcli_avp_list *list, uint32_t attrid, uint32_t vendor, uint64_t *out)
Look up the octets attribute by legacy numeric ID and reassemble a 64-bit counter from an Octets/Giga...
int radcli_avp_list_error(const radcli_avp_list *list)
Check whether any radcli_avp_add_*()/_by_num() call on list has ever failed.
void radcli_avp_list_free(radcli_avp_list *list)
Free a list and every attribute it holds.
radcli_avp_iter radcli_avp_list_iter(const radcli_avp_list *list)
Begin iterating list.
const radcli_avp * radcli_avp_get(const radcli_avp_list *list, const radcli_attr_def *def, unsigned idx)
Find the idx-th occurrence of an attribute in a list.
int radcli_avp_get_ip6(const radcli_avp *a, struct in6_addr *out, unsigned *prefix)
Read an attribute's value as an IPv6 address or prefix.
int radcli_avp_add_ip6(radcli_avp_list *list, const radcli_attr_def *def, const struct in6_addr *value, unsigned prefix)
Append an IPv6-address or IPv6-prefix-typed attribute.
int radcli_avp_get_gigawords64(const radcli_ctx *ctx, const radcli_avp_list *list, const radcli_attr_def *octets, uint64_t *out)
Reassemble a 64-bit counter from an Octets/Gigawords attribute pair.
int radcli_avp_add_ip4(radcli_avp_list *list, const radcli_attr_def *def, struct in_addr value)
Append an IPv4-address-typed attribute from a struct in_addr.
int radcli_avp_get_ip4prefix(const radcli_avp *a, struct in_addr *out, unsigned *prefix)
Read an attribute's value as an IPv4 prefix.
int radcli_avp_add_gigawords64(radcli_ctx *ctx, radcli_avp_list *list, const radcli_attr_def *octets, uint64_t value)
Append a 64-bit counter as an Octets/Gigawords attribute pair.
int radcli_avp_add_bytes(radcli_avp_list *list, const radcli_attr_def *def, const void *value, size_t len)
Append an attribute holding an arbitrary byte string.
int radcli_avp_get_uint32(const radcli_avp *a, uint32_t *out)
Read an attribute's value as an integer/IPv4-address/date.
radcli_avp_list * radcli_avp_list_new(void)
Create an empty attribute-value pair list.
int radcli_avp_add_gigawords64_by_num(radcli_ctx *ctx, radcli_avp_list *list, uint32_t attrid, uint32_t vendor, uint64_t value)
Look up the octets attribute by legacy numeric ID and append a 64-bit counter as an Octets/Gigawords ...
const radcli_attr_def * radcli_avp_def(const radcli_avp *a)
Return the attribute definition of a.
int radcli_avp_add_uint32(radcli_avp_list *list, const radcli_attr_def *def, uint32_t value)
Append an integer/IPv4-address/date-typed attribute.
const radcli_avp * radcli_avp_iter_next(radcli_avp_iter *it)
Return the current attribute and advance.
int radcli_avp_get_bytes(const radcli_avp *a, const void **out, size_t *len)
Read an attribute's value as raw bytes.
int radcli_avp_add_str(radcli_avp_list *list, const radcli_attr_def *def, const char *value)
Append a string- or text-typed attribute.
int radcli_avp_add_uint64(radcli_avp_list *list, const radcli_attr_def *def, uint64_t value)
Append a 64-bit integer- or ifid-typed attribute.
const char * radcli_avp_get_cstr(const radcli_avp *a)
Read an attribute's value as a NUL-terminated string, with no allocation or copy.
radcli_ctx * radcli_ctx_new(unsigned flags)
Create an empty context, ready for radcli_ctx_set_opt_str()/ _set_opt_int() and radcli_ctx_apply() – ...
int radcli_ctx_set_opt_str(radcli_ctx *ctx, radcli_opt_id opt, const char *val)
Set a string-typed configuration option.
const char * radcli_ctx_get_opt_str(const radcli_ctx *ctx, radcli_opt_id opt)
Read back a string-typed configuration option.
int radcli_ctx_set_opt_int(radcli_ctx *ctx, radcli_opt_id opt, long val)
Set an integer-typed configuration option.
int radcli_ctx_apply(radcli_ctx *ctx)
Validate the options set so far and initialise the transport.
int radcli_ctx_read_dictionary(radcli_ctx *ctx, const char *path)
Load an additional attribute dictionary.
radcli_ctx * radcli_ctx_read_config(const char *filename, unsigned flags)
Create a context by parsing a config file – the main, recommended way to configure radcli.
void radcli_ctx_free(radcli_ctx *ctx)
Release a context.
int radcli_ctx_read_dictionary_from_buffer(radcli_ctx *ctx, const char *buf, size_t size)
Load an additional attribute dictionary from an in-memory buffer.
int radcli_ctx_set_tls_psk(radcli_ctx *ctx, const void *identity, size_t identity_len, const uint8_t *key, size_t keylen)
Set the RFC 6614/7360 TLS-transport Pre-Shared Key credentials for the configured authserver.
int radcli_ctx_set_secret(radcli_ctx *ctx, unsigned target_mask, const char *secret)
Set the RADIUS shared secret for the configured authserver and/or acctserver.
int radcli_ctx_get_opt_int(const radcli_ctx *ctx, radcli_opt_id opt, long *out)
Read back an integer-typed configuration option.
@ RADCLI_SECRET_AUTH
Applies to the configured authserver (Access-Request).
@ RADCLI_SECRET_ACCT
Applies to the configured acctserver (Accounting-Request).
@ RADCLI_CTX_NO_BUILTIN_DICT
Skip loading the built-in RFC 2865/2866/2869 dictionary.
const radcli_attr_def * radcli_dict_lookup(const radcli_ctx *ctx, const char *name)
Look up a dictionary attribute by its canonical name.
const radcli_attr_def * radcli_dict_lookup_num(const radcli_ctx *ctx, uint32_t attrid, uint32_t vendor)
Look up a dictionary attribute by its legacy numeric ID and vendor.
const char * radcli_attr_def_name(const radcli_attr_def *def)
Return an attribute definition's canonical name.
const radcli_attr_def * radcli_dict_lookup_oid(const radcli_ctx *ctx, const char *oid)
Look up a dictionary attribute by RFC 6929 §2.7 OID notation.
radcli_attr_type radcli_attr_def_type(const radcli_attr_def *def)
Return an attribute definition's wire type.
int radcli_attr_def_oid(const radcli_attr_def *def, char *buf, size_t buflen)
Render an attribute definition's RFC 6929 §2.7 OID notation.
int radcli_dict_lookup_value(const radcli_ctx *ctx, const radcli_attr_def *def, const char *name, uint32_t *out)
Resolve a dictionary VALUE by name, scoped to one attribute.
int radcli_request_perform(radcli_request *r, unsigned flags)
Send a request, optionally waiting for the reply.
int radcli_aaa(radcli_ctx *ctx, radcli_code code, const radcli_avp_list *send, radcli_code *out_code, radcli_avp_list **out_attrs)
Perform an authentication or accounting exchange with Acct-Delay-Time autofill and fail-over across e...
const radcli_avp_list * radcli_request_attrs(const radcli_request *r)
Return the reply's decoded attributes.
const char * radcli_request_server(const radcli_request *r)
Return the name of the server a request was (or will be) sent to.
int radcli_request_done(radcli_request *r)
Report r's outcome once radcli_ctx_dispatch() has resolved it – a pure state query,...
radcli_request * radcli_request_new(radcli_ctx *ctx, radcli_code code, const radcli_avp_list *send)
Create a request to send.
void radcli_request_free(radcli_request *r)
Release a request.
radcli_code radcli_request_code(const radcli_request *r)
Return the reply's RADIUS code.
@ RADCLI_TIMEOUT
No reply from any address the server name resolved to.
@ RADCLI_ERROR
Malformed input, a verification failure, or no server configured.
@ RADCLI_OK
A validated reply was received; see radcli_request_code() for which one.
@ RADCLI_REQUEST_SENDONLY