int expected_match,
TR_FILTER_ACTION expected_action)
{
- void *target=NULL;
+ TR_FILTER_TARGET *target=NULL;
TR_FILTER_SET *filts=NULL;
TR_FILTER_ACTION action=TR_FILTER_ACTION_UNKNOWN;
/* load the target req or inforec */
switch(ftype) {
case TR_FILTER_TYPE_TID_INBOUND:
- target=load_tid_req(target_fname);
+ target=tr_filter_target_tid_req(NULL, load_tid_req(target_fname));
break;
case TR_FILTER_TYPE_TRP_INBOUND:
case TR_FILTER_TYPE_TRP_OUTBOUND:
- target=load_inforec(target_fname);
+ /* TODO: read realm and community */
+ target=tr_filter_target_trp_inforec(NULL, load_inforec(target_fname), NULL, NULL);
break;
default:
tr_filter_set_free(filts);
switch(ftype) {
case TR_FILTER_TYPE_TID_INBOUND:
- tid_req_free((TID_REQ *)target);
+ tid_req_free(target->tid_req);
break;
case TR_FILTER_TYPE_TRP_INBOUND:
case TR_FILTER_TYPE_TRP_OUTBOUND:
- trp_inforec_free((TRP_INFOREC *)target);
+ trp_inforec_free(target->trp_inforec);
+ if (target->realm!=NULL)
+ tr_free_name(target->realm);
+ if (target->comm!=NULL)
+ tr_free_name(target->comm);
break;
default:
printf("Unknown filter type.\n");
}
+ tr_filter_target_free(target);
return 1;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <talloc.h>
#include <assert.h>
/* Function types for handling filter fields generally. All target values
* are represented as strings in a TR_NAME.
*/
-typedef int (*TR_FILTER_FIELD_CMP)(void *target, TR_NAME *val); /* returns 1 on match, 0 on no match */
-typedef TR_NAME *(*TR_FILTER_FIELD_GET)(void *target); /* returns string form of the field value */
+typedef int (*TR_FILTER_FIELD_CMP)(TR_FILTER_TARGET *target, TR_NAME *val); /* returns 1 on match, 0 on no match */
+typedef TR_NAME *(*TR_FILTER_FIELD_GET)(TR_FILTER_TARGET *target); /* returns string form of the field value */
/* static handler prototypes */
-static int tr_ff_cmp_tid_rp_realm(void *rp_req_arg, TR_NAME *val);
-static TR_NAME *tr_ff_get_tid_rp_realm(void *rp_req_arg);
-static int tr_ff_cmp_trp_info_type(void *inforec_arg, TR_NAME *val);
-static TR_NAME *tr_ff_get_trp_info_type(void *inforec_arg);
+static int tr_ff_cmp_tid_rp_realm(TR_FILTER_TARGET *target, TR_NAME *val);
+static TR_NAME *tr_ff_get_tid_rp_realm(TR_FILTER_TARGET *target);
+static int tr_ff_cmp_trp_info_type(TR_FILTER_TARGET *target, TR_NAME *val);
+static TR_NAME *tr_ff_get_trp_info_type(TR_FILTER_TARGET *target);
/**
* Filter field handler table
return NULL;
}
-static int tr_ff_cmp_tid_rp_realm(void *rp_req_arg, TR_NAME *val)
+static TR_FILTER_TARGET *tr_filter_target_new(TALLOC_CTX *mem_ctx)
{
- TID_REQ *req=talloc_get_type_abort(rp_req_arg, TID_REQ);
+ TR_FILTER_TARGET *target=talloc(mem_ctx, TR_FILTER_TARGET);
+ if (target) {
+ target->trp_inforec=NULL;
+ target->comm=NULL;
+ target->realm=NULL;
+ target->tid_req=NULL;
+ }
+ return target;
+}
+void tr_filter_target_free(TR_FILTER_TARGET *target)
+{
+ talloc_free(target);
+}
+
+/**
+ * Create a filter target for a TID request. Does not change the context of the request,
+ * so this is only valid until that is freed.
+ *
+ * @param mem_ctx talloc context for the object
+ * @param req TID request object
+ * @return pointer to a TR_FILTER_TARGET structure, or null on allocation failure
+ */
+TR_FILTER_TARGET *tr_filter_target_tid_req(TALLOC_CTX *mem_ctx, TID_REQ *req)
+{
+ TR_FILTER_TARGET *target=tr_filter_target_new(mem_ctx);
+ if (target)
+ target->tid_req=req; /* borrowed, not adding to our context */
+ return target;
+}
+
+/**
+ * Create a filter target for a TRP inforec. Does not change the context of the inforec or duplicate TR_NAMEs,
+ * so this is only valid until those are freed.
+ *
+ * @param mem_ctx talloc context for the object
+ * @param inforec TRP inforec
+ * @param realm realm name
+ * @param comm community name
+ * @return pointer to a TR_FILTER_TARGET structure, or null on allocation failure
+ */
+TR_FILTER_TARGET *tr_filter_target_trp_inforec(TALLOC_CTX *mem_ctx, TRP_INFOREC *inforec, TR_NAME *realm, TR_NAME *comm)
+{
+ TR_FILTER_TARGET *target=tr_filter_target_new(mem_ctx);
+ if (target) {
+ target->trp_inforec = inforec; /* borrowed, not adding to our context */
+ target->realm=realm;
+ target->comm=comm;
+ }
+ return target;
+}
+
+static int tr_ff_cmp_tid_rp_realm(TR_FILTER_TARGET *target, TR_NAME *val)
+{
+ TID_REQ *req=target->tid_req;
assert(req);
return 0==tr_name_cmp(val, req->rp_realm);
}
-static TR_NAME *tr_ff_get_tid_rp_realm(void *rp_req_arg)
+static TR_NAME *tr_ff_get_tid_rp_realm(TR_FILTER_TARGET *target)
{
- TID_REQ *req=talloc_get_type_abort(rp_req_arg, TID_REQ);
+ TID_REQ *req=target->tid_req;
assert(req);
return tr_dup_name(req->rp_realm);
}
-static int tr_ff_cmp_trp_info_type(void *inforec_arg, TR_NAME *val)
+static int tr_ff_cmp_trp_info_type(TR_FILTER_TARGET *target, TR_NAME *val)
{
- TRP_INFOREC *inforec=talloc_get_type_abort(inforec_arg, TRP_INFOREC);
+ TRP_INFOREC *inforec=target->trp_inforec;
char *valstr=NULL;
int val_type=0;
return (val_type==inforec->type);
}
-static TR_NAME *tr_ff_get_trp_info_type(void *inforec_arg)
+static TR_NAME *tr_ff_get_trp_info_type(TR_FILTER_TARGET *target)
{
- TRP_INFOREC *inforec=talloc_get_type_abort(inforec_arg, TRP_INFOREC);
+ TRP_INFOREC *inforec=target->trp_inforec;
return tr_new_name(trp_inforec_type_to_string(inforec->type));
}
* @param out_action Action to be carried out (output)
* @return TR_FILTER_MATCH or TR_FILTER_NO_MATCH
*/
-int tr_filter_apply(void *target,
+int tr_filter_apply(TR_FILTER_TARGET *target,
TR_FILTER *filt,
TR_CONSTRAINT_SET **constraints,
TR_FILTER_ACTION *out_action)
}
/* returns 1 if the spec matches */
-int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, void *target)
+int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, TR_FILTER_TARGET *target)
{
struct tr_filter_field_entry *field=NULL;
TR_NAME *name=NULL;
TR_FILTER_SET *next;
};
+/**
+ * Structure to hold information needed to filter different targets.
+ */
+typedef struct tr_filter_target {
+ /* An inforec also needs realm and community information */
+ TRP_INFOREC *trp_inforec;
+ TR_NAME *realm;
+ TR_NAME *comm;
+
+ /* a TID request has all the data it needs to be filtered */
+ TID_REQ *tid_req;
+} TR_FILTER_TARGET;
+
TR_FILTER_SET *tr_filter_set_new(TALLOC_CTX *mem_ctx);
void tr_filter_set_free(TR_FILTER_SET *fs);
int tr_filter_set_add(TR_FILTER_SET *set, TR_FILTER *new);
void tr_fspec_add_match(TR_FSPEC *fspec, TR_NAME *match);
-int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, void *target);
+int tr_fspec_matches(TR_FSPEC *fspec, TR_FILTER_TYPE ftype, TR_FILTER_TARGET *target);
/*In tr_constraint.c and exported, but not really a public symbol; needed by tr_filter.c and by tr_constraint.c*/
int TR_EXPORT tr_prefix_wildcard_match(const char *str, const char *wc_str);
-int tr_filter_apply(void *target, TR_FILTER *filt, TR_CONSTRAINT_SET **constraints, TR_FILTER_ACTION *out_action);
+int tr_filter_apply(TR_FILTER_TARGET *target, TR_FILTER *filt, TR_CONSTRAINT_SET **constraints, TR_FILTER_ACTION *out_action);
+void tr_filter_target_free(TR_FILTER_TARGET *target);
+TR_FILTER_TARGET *tr_filter_target_tid_req(TALLOC_CTX *mem_ctx, TID_REQ *req);
+TR_FILTER_TARGET *tr_filter_target_trp_inforec(TALLOC_CTX *mem_ctx, TRP_INFOREC *inforec, TR_NAME *realm, TR_NAME *comm);
TR_CONSTRAINT_SET *tr_constraint_set_from_fline(TR_FLINE *fline);
unsigned int resp_frac_numer=cfg_mgr->active->internal->tid_resp_numer;
unsigned int resp_frac_denom=cfg_mgr->active->internal->tid_resp_denom;
TR_RESP_COOKIE *payload=NULL;
+ TR_FILTER_TARGET *target=NULL;
int ii=0;
int retval=-1;
* well. Need to verify that this is acceptable behavior, but it's what we've always done. */
fwd_req->cons=orig_req->cons;
- if ((TR_FILTER_NO_MATCH == tr_filter_apply(orig_req,
- tr_filter_set_get(tids->rp_gss->filters,
- TR_FILTER_TYPE_TID_INBOUND),
- &(fwd_req->cons),
- &oaction)) ||
- (TR_FILTER_ACTION_ACCEPT != oaction)) {
+ target=tr_filter_target_tid_req(tmp_ctx, orig_req);
+ if (target==NULL) {
+ /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */
+ tr_crit("tid_req_handler: Unable to allocate filter target, cannot apply filter!");
+ }
+ if ((target==NULL)
+ || (TR_FILTER_NO_MATCH == tr_filter_apply(target,
+ tr_filter_set_get(tids->rp_gss->filters,
+ TR_FILTER_TYPE_TID_INBOUND),
+ &(fwd_req->cons),
+ &oaction))
+ || (TR_FILTER_ACTION_ACCEPT != oaction)) {
tr_notice("tr_tids_req_handler: RP realm (%s) does not match RP Realm filter for GSS name", orig_req->rp_realm->buf);
tids_send_err_response(tids, orig_req, "RP Realm filter error");
retval=-1;
* @param trps Active TRPS instance
* @param peer_name Name of peer that sent this inforec
* @param rec Inforec to filter
+ * @param realm Name of realm
+ * @param comm Name of community
* @return 1 if accepted by the filter, 0 otherwise
*/
-static int trps_filter_inbound_inforec(TRPS_INSTANCE *trps, TR_NAME *peer_name, TRP_INFOREC *rec)
+static int trps_filter_inbound_inforec(TRPS_INSTANCE *trps, TR_NAME *peer_name, TRP_INFOREC *rec, TR_NAME *realm, TR_NAME *comm)
{
TRP_PEER *peer=NULL;
TR_FILTER_ACTION action=TR_FILTER_ACTION_REJECT;
+ TR_FILTER_TARGET *target=NULL;
+ int retval=0;
/* Look up the peer. For inbound messages, the peer is identified by its GSS name */
peer=trps_get_peer_by_gssname(trps, peer_name);
}
/* tr_filter_apply() and tr_filter_set_get() handle null filter sets/filters by rejecting */
- if ((TR_FILTER_NO_MATCH==tr_filter_apply(rec,
- tr_filter_set_get(peer->filters, TR_FILTER_TYPE_TRP_INBOUND),
- NULL,
- &action))
+ target=tr_filter_target_trp_inforec(NULL, rec, realm, comm);
+ if (target==NULL) {
+ /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */
+ tr_crit("trps_filter_inbound_inforec: Unable to allocate filter target, cannot apply filter!");
+ }
+ if ((target==NULL)
+ || (TR_FILTER_NO_MATCH==tr_filter_apply(target,
+ tr_filter_set_get(peer->filters, TR_FILTER_TYPE_TRP_INBOUND),
+ NULL,
+ &action))
|| (action!=TR_FILTER_ACTION_ACCEPT)) {
- /* either the filter did not match or it matched a reject rule */
- return 0;
- }
+ /* either the filter did not match or it matched a reject rule or allocating the target failed */
+ retval=0;
+ } else
+ retval=1;
+ if (target!=NULL)
+ tr_filter_target_free(target);
/* filter matched an accept rule */
- return 1;
+ return retval;
}
}
for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
- if (!trps_filter_inbound_inforec(trps, trp_upd_get_peer(upd), rec)) {
+ if (!trps_filter_inbound_inforec(trps,
+ trp_upd_get_peer(upd),
+ rec,
+ trp_upd_get_realm(upd),
+ trp_upd_get_comm(upd))) {
tr_debug("trps_handle_update: inforec rejected by filter.");
continue; /* just go on to the next record */
}
{
TRP_INFOREC *this=NULL, *next=NULL;
TR_FILTER_ACTION action=TR_FILTER_ACTION_REJECT;
+ TR_FILTER_TARGET *target=NULL;
for(this=trp_upd_get_inforec(upd); this!=NULL; this=next) {
next=this->next;
- if ((TR_FILTER_NO_MATCH==tr_filter_apply(this, filt, NULL, &action))
+ target=tr_filter_target_trp_inforec(NULL, this, trp_upd_get_realm(upd), trp_upd_get_comm(upd));
+ if (target==NULL) {
+ /* TODO: signal that filtering failed. Until then, just filter everything and give an error message. */
+ tr_crit("trps_filter_one_outbound_update: Unable to allocate filter target, cannot apply filter!");
+ }
+ if ((target==NULL)
+ || (TR_FILTER_NO_MATCH==tr_filter_apply(target, filt, NULL, &action))
|| (action!=TR_FILTER_ACTION_ACCEPT)) {
- /* Either no filter matched or one matched and rejected this record */
+ /* Either no filter matched or one matched and rejected this record.
+ * Also filter out record if we were unable to allocate a target. */
trp_upd_remove_inforec(upd, this); /* "this" is now invalid */
}
+ if (target!=NULL)
+ tr_filter_target_free(target);
}
}
static TRP_RC trps_update_one_peer(TRPS_INSTANCE *trps,
TRP_PEER *peer,
TRP_UPDATE_TYPE update_type,
- TR_NAME *comm,
- TR_NAME *realm)
+ TR_NAME *realm,
+ TR_NAME *comm)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
TR_MSG msg; /* not a pointer! */
return trps_update_one_peer(trps,
trps_get_peer_by_gssname(trps, trp_req_get_peer(req)),
TRP_UPDATE_REQUESTED,
- comm,
- realm);
+ realm,
+ comm);
}