static int __noinline npf_mk_code(prop_object_t obj, int type, void **code, size_t *csize, prop_dictionary_t errdict) { const void *cptr; size_t clen; void *bc; if (type != NPF_CODE_BPF) { return ENOTSUP; } cptr = prop_data_data_nocopy(obj); if (cptr == NULL || (clen = prop_data_size(obj)) == 0) { NPF_ERR_DEBUG(errdict); return EINVAL; } if (!npf_bpf_validate(cptr, clen)) { NPF_ERR_DEBUG(errdict); return EINVAL; } bc = kmem_alloc(clen, KM_SLEEP); memcpy(bc, cptr, clen); *code = bc; *csize = clen; return 0; }
static int __noinline npf_mk_ncode(prop_object_t obj, void **code, size_t *csize, prop_dictionary_t errdict) { const void *ncptr; int nc_err, errat; size_t nc_size; void *nc; /* * Allocate, copy and validate n-code. XXX: Inefficient. */ ncptr = prop_data_data_nocopy(obj); nc_size = prop_data_size(obj); if (ncptr == NULL || nc_size > NPF_NCODE_LIMIT) { NPF_ERR_DEBUG(errdict); return ERANGE; } nc = npf_ncode_alloc(nc_size); if (nc == NULL) { NPF_ERR_DEBUG(errdict); return ENOMEM; } memcpy(nc, ncptr, nc_size); nc_err = npf_ncode_validate(nc, nc_size, &errat); if (nc_err) { npf_ncode_free(nc, nc_size); prop_dictionary_set_int32(errdict, "ncode-error", nc_err); prop_dictionary_set_int32(errdict, "ncode-errat", errat); return EINVAL; } *code = nc; *csize = nc_size; return 0; }
static int __noinline npf_mk_natlist(npf_ruleset_t *nset, prop_array_t natlist, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t natdict; int error; /* NAT policies - array. */ if (prop_object_type(natlist) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } error = 0; it = prop_array_iterator(natlist); while ((natdict = prop_object_iterator_next(it)) != NULL) { npf_rule_t *rl = NULL; npf_natpolicy_t *np; /* NAT policy - dictionary. */ if (prop_object_type(natdict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } /* * NAT policies are standard rules, plus additional * information for translation. Make a rule. */ error = npf_mk_singlerule(natdict, NULL, &rl, errdict); if (error) { break; } npf_ruleset_insert(nset, rl); /* If rule is named, it is a group with NAT policies. */ if (prop_dictionary_get(natdict, "name") && prop_dictionary_get(natdict, "subrules")) { continue; } /* Allocate a new NAT policy and assign to the rule. */ np = npf_nat_newpolicy(natdict, nset); if (np == NULL) { NPF_ERR_DEBUG(errdict); error = ENOMEM; break; } npf_rule_setnat(rl, np); } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free entire NAT ruleset * with assigned NAT policies. */ return error; }
static int __noinline npf_mk_singlerule(prop_dictionary_t rldict, npf_rprocset_t *rpset, npf_rule_t **rlret, prop_dictionary_t errdict) { npf_rule_t *rl; const char *rname; prop_object_t obj; int p, error = 0; /* Rule - dictionary. */ if (prop_object_type(rldict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); return EINVAL; } if ((rl = npf_rule_alloc(rldict)) == NULL) { NPF_ERR_DEBUG(errdict); return EINVAL; } /* Assign rule procedure, if any. */ if (prop_dictionary_get_cstring_nocopy(rldict, "rproc", &rname)) { npf_rproc_t *rp; if (rpset == NULL) { error = EINVAL; goto err; } if ((rp = npf_rprocset_lookup(rpset, rname)) == NULL) { NPF_ERR_DEBUG(errdict); error = EINVAL; goto err; } npf_rule_setrproc(rl, rp); } /* Filter code (binary data). */ if ((obj = prop_dictionary_get(rldict, "code")) != NULL) { int type; size_t len; void *code; prop_dictionary_get_int32(rldict, "code-type", &type); error = npf_mk_code(obj, type, &code, &len, errdict); if (error) { goto err; } npf_rule_setcode(rl, type, code, len); } *rlret = rl; return 0; err: npf_rule_free(rl); prop_dictionary_get_int32(rldict, "prio", &p); /* XXX */ prop_dictionary_set_int32(errdict, "id", p); return error; }
static int __noinline npf_mk_rules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t rldict, rpdict; int error; /* Rule procedures and the ruleset - arrays. */ if (prop_object_type(rprocs) != PROP_TYPE_ARRAY || prop_object_type(rules) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } it = prop_array_iterator(rprocs); while ((rpdict = prop_object_iterator_next(it)) != NULL) { if (prop_dictionary_get(rpdict, "rproc-ptr")) { prop_object_iterator_release(it); NPF_ERR_DEBUG(errdict); return EINVAL; } } prop_object_iterator_release(it); error = 0; it = prop_array_iterator(rules); while ((rldict = prop_object_iterator_next(it)) != NULL) { prop_array_t subrules; npf_ruleset_t *rlsetsub; npf_rule_t *rl; /* Generate a single rule. */ error = npf_mk_singlerule(rldict, rprocs, &rl, errdict); if (error) { break; } npf_ruleset_insert(rlset, rl); /* Check for sub-rules and generate, if any. */ subrules = prop_dictionary_get(rldict, "subrules"); if (subrules == NULL) { /* No subrules, next.. */ continue; } rlsetsub = npf_rule_subset(rl); error = npf_mk_subrules(rlsetsub, subrules, rprocs, errdict); if (error) break; } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free the ruleset. */ return error; }
static int __noinline npf_mk_singlerule(prop_dictionary_t rldict, prop_array_t rps, npf_rule_t **rl, prop_dictionary_t errdict) { const char *rnm; npf_rproc_t *rp; prop_object_t obj; size_t nc_size; void *nc; int p, error; /* Rule - dictionary. */ if (prop_object_type(rldict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); return EINVAL; } error = 0; obj = prop_dictionary_get(rldict, "ncode"); if (obj) { /* N-code (binary data). */ error = npf_mk_ncode(obj, &nc, &nc_size, errdict); if (error) { goto err; } } else { /* No n-code. */ nc = NULL; nc_size = 0; } /* Check for rule procedure. */ if (rps && prop_dictionary_get_cstring_nocopy(rldict, "rproc", &rnm)) { rp = npf_mk_rproc(rps, rnm); if (rp == NULL) { if (nc) { npf_ncode_free(nc, nc_size); /* XXX */ } NPF_ERR_DEBUG(errdict); error = EINVAL; goto err; } } else { rp = NULL; } /* Finally, allocate and return the rule. */ *rl = npf_rule_alloc(rldict, rp, nc, nc_size); KASSERT(*rl != NULL); return 0; err: prop_dictionary_get_int32(rldict, "priority", &p); /* XXX */ prop_dictionary_set_int32(errdict, "id", p); return error; }
static int __noinline npf_mk_rules(npf_ruleset_t *rlset, prop_array_t rules, npf_rprocset_t *rpset, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t rldict; int error; if (prop_object_type(rules) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } error = 0; it = prop_array_iterator(rules); while ((rldict = prop_object_iterator_next(it)) != NULL) { npf_rule_t *rl = NULL; /* Generate a single rule. */ error = npf_mk_singlerule(rldict, rpset, &rl, errdict); if (error) { break; } npf_ruleset_insert(rlset, rl); } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free the ruleset. */ return error; }
/* * npf_mk_connlist: import a list of connections and load them. */ static int __noinline npf_mk_connlist(prop_array_t conlist, npf_ruleset_t *natlist, npf_conndb_t **conndb, prop_dictionary_t errdict) { prop_dictionary_t condict; prop_object_iterator_t it; npf_conndb_t *cd; int error = 0; /* Connection list - array */ if (prop_object_type(conlist) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } /* Create a connection database. */ cd = npf_conndb_create(); it = prop_array_iterator(conlist); while ((condict = prop_object_iterator_next(it)) != NULL) { /* Connection - dictionary. */ if (prop_object_type(condict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } /* Construct and insert the connection. */ error = npf_conn_import(cd, condict, natlist); if (error) { NPF_ERR_DEBUG(errdict); break; } } prop_object_iterator_release(it); if (error) { npf_conn_gc(cd, true, false); npf_conndb_destroy(cd); } else { *conndb = cd; } return error; }
static int npf_insert_nat_rule(prop_dictionary_t natdict, prop_dictionary_t errdict) { int error; npf_natpolicy_t *np; npf_rule_t *rl; printf("npf_insert_nat_rule\n"); if (prop_object_type(natdict) != PROP_TYPE_DICTIONARY) { printf("rossz tipus!\n"); NPF_ERR_DEBUG(errdict); return EINVAL; } /* * NAT policies are standard rules, plus additional * information for translation. Make a rule. */ error = npf_mk_singlerule(natdict, NULL, &rl, errdict); if (error) { printf("hiba a mksinglerule alatt\n"); return error; } npf_core_enter(); printf("most ruleset inserteljuk\n"); npf_ruleset_insert(npf_core_natset(), rl); /* Allocate a new NAT policy and assign to the rule. */ np = npf_nat_newpolicy(natdict, npf_core_natset()); if (np == NULL) { printf("hiba a newpolicy alatt\n"); NPF_ERR_DEBUG(errdict); return ENOMEM; } npf_rule_setnat(rl, np); npf_core_exit(); return 0; }
static int __noinline npf_mk_algs(prop_array_t alglist, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t nadict; int error = 0; it = prop_array_iterator(alglist); while ((nadict = prop_object_iterator_next(it)) != NULL) { if (npf_mk_singlealg(nadict) == NULL) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } } prop_object_iterator_release(it); return error; }
static int __noinline npf_mk_rprocs(npf_rprocset_t *rpset, prop_array_t rprocs, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t rpdict; int error = 0; it = prop_array_iterator(rprocs); while ((rpdict = prop_object_iterator_next(it)) != NULL) { npf_rproc_t *rp; if ((rp = npf_mk_singlerproc(rpdict)) == NULL) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } npf_rprocset_insert(rpset, rp); } prop_object_iterator_release(it); return error; }
static int __noinline npf_mk_subrules(npf_ruleset_t *rlset, prop_array_t rules, prop_array_t rprocs, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t rldict; int error = 0; if (prop_object_type(rules) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } it = prop_array_iterator(rules); while ((rldict = prop_object_iterator_next(it)) != NULL) { npf_rule_t *rl; error = npf_mk_singlerule(rldict, rprocs, &rl, errdict); if (error) { break; } npf_ruleset_insert(rlset, rl); } prop_object_iterator_release(it); return error; }
static int __noinline npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t tbldict; int error = 0; /* Tables - array. */ if (prop_object_type(tables) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } it = prop_array_iterator(tables); while ((tbldict = prop_object_iterator_next(it)) != NULL) { const char *name; npf_table_t *t; u_int tid; int type; /* Table - dictionary. */ if (prop_object_type(tbldict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } /* Table name, ID and type. Validate them. */ if (!prop_dictionary_get_cstring_nocopy(tbldict, "name", &name)) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } prop_dictionary_get_uint32(tbldict, "id", &tid); prop_dictionary_get_int32(tbldict, "type", &type); error = npf_table_check(tblset, name, tid, type); if (error) { NPF_ERR_DEBUG(errdict); break; } /* Get the entries or binary data. */ prop_array_t ents = prop_dictionary_get(tbldict, "entries"); prop_object_t obj = prop_dictionary_get(tbldict, "data"); void *blob = prop_data_data(obj); size_t size = prop_data_size(obj); if (type == NPF_TABLE_CDB && (blob == NULL || size == 0)) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } if (type == NPF_TABLE_HASH) { size = 1024; /* XXX */ } /* Create and insert the table. */ t = npf_table_create(name, tid, type, blob, size); if (t == NULL) { NPF_ERR_DEBUG(errdict); error = ENOMEM; break; } error = npf_tableset_insert(tblset, t); KASSERT(error == 0); if (ents && (error = npf_mk_table_entries(t, ents)) != 0) { NPF_ERR_DEBUG(errdict); break; } } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free the tableset. */ return error; }
static int __noinline npf_mk_tables(npf_tableset_t *tblset, prop_array_t tables, prop_dictionary_t errdict) { prop_object_iterator_t it; prop_dictionary_t tbldict; int error = 0; /* Tables - array. */ if (prop_object_type(tables) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); return EINVAL; } it = prop_array_iterator(tables); while ((tbldict = prop_object_iterator_next(it)) != NULL) { prop_dictionary_t ent; prop_object_iterator_t eit; prop_array_t entries; npf_table_t *t; u_int tid; int type; /* Table - dictionary. */ if (prop_object_type(tbldict) != PROP_TYPE_DICTIONARY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } /* Table ID and type. */ prop_dictionary_get_uint32(tbldict, "id", &tid); prop_dictionary_get_int32(tbldict, "type", &type); /* Validate them, check for duplicate IDs. */ error = npf_table_check(tblset, tid, type); if (error) break; /* Create and insert the table. */ t = npf_table_create(tid, type, 1024); /* XXX */ if (t == NULL) { NPF_ERR_DEBUG(errdict); error = ENOMEM; break; } error = npf_tableset_insert(tblset, t); KASSERT(error == 0); /* Entries. */ entries = prop_dictionary_get(tbldict, "entries"); if (prop_object_type(entries) != PROP_TYPE_ARRAY) { NPF_ERR_DEBUG(errdict); error = EINVAL; break; } eit = prop_array_iterator(entries); while ((ent = prop_object_iterator_next(eit)) != NULL) { const npf_addr_t *addr; npf_netmask_t mask; int alen; /* Get address and mask. Add a table entry. */ prop_object_t obj = prop_dictionary_get(ent, "addr"); addr = (const npf_addr_t *)prop_data_data_nocopy(obj); prop_dictionary_get_uint8(ent, "mask", &mask); alen = prop_data_size(obj); error = npf_table_insert(tblset, tid, alen, addr, mask); if (error) break; } prop_object_iterator_release(eit); if (error) break; } prop_object_iterator_release(it); /* * Note: in a case of error, caller will free the tableset. */ return error; }