static unsigned match_enrich(kd_tree *t, int *coeffs, int x, int y, int *prev) { int k = t->k, *start = t->start; kd_node *n = kdt_query(t, coeffs); // set results of query int64_t res = match_score(coeffs, n, k); int best[] = {INT_MAX, UNPACK_SCORE(res)}; int pos[] = {INT_MAX, n->value[UNPACK_IDX(res)] - start}; pos[0] = pos[1]; // hack for (x,y) == (0,0) // now check 2 best matches for the left if (x) { check_guide(t, coeffs, prev[-1], best, pos); check_guide(t, coeffs, prev[-2], best, pos); } // check 2 best matches for top if (y) { check_guide(t, coeffs, prev[0], best, pos); check_guide(t, coeffs, prev[1], best, pos); } // set prev to best matches prev[0] = pos[0]; prev[1] = pos[1]; return pos[1]; }
/* * Lists nat64lsn states. * Data layout (v0)(current): * Request: [ ipfw_obj_header ipfw_obj_data [ uint64_t ]] * Reply: [ ipfw_obj_header ipfw_obj_data [ * ipfw_nat64lsn_stg ipfw_nat64lsn_state x N] ] * * Returns 0 on success */ static int nat64lsn_states(struct ip_fw_chain *ch, ip_fw3_opheader *op3, struct sockopt_data *sd) { ipfw_obj_header *oh; ipfw_obj_data *od; ipfw_nat64lsn_stg *stg; struct nat64lsn_cfg *cfg; struct nat64lsn_portgroup *pg, *pg_next; uint64_t next_idx; size_t sz; uint32_t addr, states; uint16_t port; uint8_t nat_proto; sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_data) + sizeof(uint64_t); /* Check minimum header size */ if (sd->valsize < sz) return (EINVAL); oh = (ipfw_obj_header *)sd->kbuf; od = (ipfw_obj_data *)(oh + 1); if (od->head.type != IPFW_TLV_OBJDATA || od->head.length != sz - sizeof(ipfw_obj_header)) return (EINVAL); next_idx = *(uint64_t *)(od + 1); /* Translate index to the request position to start from */ UNPACK_IDX(next_idx, addr, nat_proto, port); if (nat_proto >= NAT_MAX_PROTO) return (EINVAL); if (nat_proto == 0 && addr != 0) return (EINVAL); IPFW_UH_RLOCK(ch); cfg = nat64lsn_find(CHAIN_TO_SRV(ch), oh->ntlv.name, oh->ntlv.set); if (cfg == NULL) { IPFW_UH_RUNLOCK(ch); return (ESRCH); } /* Fill in starting point */ if (addr == 0) { addr = cfg->prefix4; nat_proto = 1; port = 0; } if (addr < cfg->prefix4 || addr > cfg->pmask4) { IPFW_UH_RUNLOCK(ch); DPRINTF(DP_GENERIC | DP_STATE, "XXX: %lu %u %u", next_idx, addr, cfg->pmask4); return (EINVAL); } sz = sizeof(ipfw_obj_header) + sizeof(ipfw_obj_data) + sizeof(ipfw_nat64lsn_stg); if (sd->valsize < sz) return (ENOMEM); oh = (ipfw_obj_header *)ipfw_get_sopt_space(sd, sz); od = (ipfw_obj_data *)(oh + 1); od->head.type = IPFW_TLV_OBJDATA; od->head.length = sz - sizeof(ipfw_obj_header); stg = (ipfw_nat64lsn_stg *)(od + 1); pg = get_first_pg(cfg, &addr, &nat_proto, &port); if (pg == NULL) { /* No states */ stg->next_idx = 0xFF; stg->count = 0; IPFW_UH_RUNLOCK(ch); return (0); } states = 0; pg_next = NULL; while (pg != NULL) { pg_next = get_next_pg(cfg, &addr, &nat_proto, &port); if (pg_next == NULL) stg->next_idx = 0xFF; else stg->next_idx = PACK_IDX(addr, nat_proto, port); if (export_pg_states(cfg, pg, stg, sd) != 0) { IPFW_UH_RUNLOCK(ch); return (states == 0 ? ENOMEM: 0); } states += stg->count; od->head.length += stg->count * sizeof(ipfw_nat64lsn_state); sz += stg->count * sizeof(ipfw_nat64lsn_state); if (pg_next != NULL) { sz += sizeof(ipfw_nat64lsn_stg); if (sd->valsize < sz) break; stg = (ipfw_nat64lsn_stg *)ipfw_get_sopt_space(sd, sizeof(ipfw_nat64lsn_stg)); } pg = pg_next; } IPFW_UH_RUNLOCK(ch); return (0); }