int lookup_done(void *context) { struct lookup_context *ctxt = (struct lookup_context *) context; int rv = close_parse(ctxt->parse); free(ctxt); cache_release(); return rv; }
static void cli_complete(char *line) { const HIST_ENTRY *hist; const char *c; LIST_HEAD(msgs); int len; char *s; if (line == NULL) { printf("\n"); cli_exit(); exit(0); } line = cli_append_multiline(line); if (line == NULL) return; for (c = line; *c != '\0'; c++) if (!isspace(*c)) break; if (*c == '\0') return; if (!strcmp(line, "quit")) { cli_exit(); exit(0); } /* avoid duplicate history entries */ hist = history_get(history_length); if (hist == NULL || strcmp(hist->line, line)) add_history(line); len = strlen(line); s = xmalloc(len + 2); snprintf(s, len + 2, "%s\n", line); xfree(line); line = s; parser_init(state, &msgs); scanner_push_buffer(scanner, &indesc_cli, line); nft_run(scanner, state, &msgs); erec_print_list(stdout, &msgs); xfree(line); cache_release(); iface_cache_release(); }
/* * Allow single attribute values to be retrieved from the cache. */ static ssize_t cache_xlat(void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace) { rlm_cache_entry_t *c; rlm_cache_t *inst = instance; rlm_cache_handle_t *handle; VALUE_PAIR *vp, *vps; pair_lists_t list; DICT_ATTR const *target; char const *p = fmt; size_t len; int ret = 0; list = radius_list_name(&p, PAIR_LIST_REQUEST); target = dict_attrbyname(p); if (!target) { REDEBUG("Unknown attribute \"%s\"", p); return -1; } if (cache_acquire(&handle, inst, request) < 0) return -1; switch (cache_find(&c, inst, request, handle, fmt)) { case RLM_MODULE_OK: /* found */ break; case RLM_MODULE_NOTFOUND: /* not found */ *out = '\0'; return 0; default: return -1; } switch (list) { case PAIR_LIST_REQUEST: vps = c->packet; break; case PAIR_LIST_REPLY: vps = c->reply; break; case PAIR_LIST_CONTROL: vps = c->control; break; case PAIR_LIST_UNKNOWN: REDEBUG("Unknown list qualifier in \"%s\"", fmt); ret = -1; goto finish; default: REDEBUG("Unsupported list \"%s\"", fr_int2str(pair_lists, list, "<UNKNOWN>")); ret = -1; goto finish; } vp = pairfind(vps, target->attr, target->vendor, TAG_ANY); if (!vp) { RDEBUG("No instance of this attribute has been cached"); *out = '\0'; goto finish; } len = vp_prints_value(out, freespace, vp, 0); if (is_truncated(len, freespace)) { REDEBUG("Insufficient buffer space to write cached value"); ret = -1; goto finish; } finish: cache_free(inst, &c); cache_release(inst, request, &handle); return ret; }
/* * Do caching checks. Since we can update ANY VP list, we do * exactly the same thing for all sections (autz / auth / etc.) * * If you want to cache something different in different sections, * configure another cache module. */ static rlm_rcode_t CC_HINT(nonnull) mod_cache_it(void *instance, REQUEST *request) { rlm_cache_entry_t *c; rlm_cache_t *inst = instance; rlm_cache_handle_t *handle; vp_cursor_t cursor; VALUE_PAIR *vp; char buffer[1024]; rlm_rcode_t rcode; int ttl = inst->ttl; if (radius_xlat(buffer, sizeof(buffer), request, inst->key, NULL, NULL) < 0) return RLM_MODULE_FAIL; if (buffer[0] == '\0') { REDEBUG("Zero length key string is invalid"); return RLM_MODULE_INVALID; } if (cache_acquire(&handle, inst, request) < 0) return RLM_MODULE_FAIL; rcode = cache_find(&c, inst, request, &handle, buffer); if (rcode == RLM_MODULE_FAIL) goto finish; rad_assert(handle); /* * If Cache-Status-Only == yes, only return whether we found a * valid cache entry */ vp = pairfind(request->config_items, PW_CACHE_STATUS_ONLY, 0, TAG_ANY); if (vp && vp->vp_integer) { rcode = c ? RLM_MODULE_OK: RLM_MODULE_NOTFOUND; goto finish; } /* * Update the expiry time based on the TTL. * A TTL of 0 means "delete from the cache". * A TTL < 0 means "delete from the cache and recreate the entry". */ vp = pairfind(request->config_items, PW_CACHE_TTL, 0, TAG_ANY); if (vp) ttl = vp->vp_signed; /* * If there's no existing cache entry, go and create a new one. */ if (!c) { if (ttl <= 0) ttl = inst->ttl; goto insert; } /* * Expire the entry if requested to do so */ if (vp) { if (ttl == 0) { cache_expire(inst, request, &handle, &c); RDEBUG("Forcing expiry of entry"); rcode = RLM_MODULE_OK; goto finish; } if (ttl < 0) { RDEBUG("Forcing expiry of existing entry"); cache_expire(inst, request, &handle, &c); ttl *= -1; goto insert; } c->expires = request->timestamp + ttl; RDEBUG("Setting TTL to %d", ttl); } /* * Cache entry was still valid, so we merge it into the request * and return. No need to add a new entry. */ cache_merge(inst, request, c); rcode = RLM_MODULE_UPDATED; goto finish; insert: /* * If Cache-Read-Only == yes, then we only allow already cached entries * to be merged into the request */ vp = pairfind(request->config_items, PW_CACHE_READ_ONLY, 0, TAG_ANY); if (vp && vp->vp_integer) { rcode = RLM_MODULE_NOTFOUND; goto finish; } /* * Create a new entry. */ rcode = cache_insert(inst, request, &handle, buffer, ttl); rad_assert(handle); finish: cache_free(inst, &c); cache_release(inst, request, &handle); /* * Clear control attributes */ for (vp = fr_cursor_init(&cursor, &request->config_items); vp; vp = fr_cursor_next(&cursor)) { if (vp->da->vendor == 0) switch (vp->da->attr) { case PW_CACHE_TTL: case PW_CACHE_STATUS_ONLY: case PW_CACHE_READ_ONLY: case PW_CACHE_MERGE: vp = fr_cursor_remove(&cursor); talloc_free(vp); break; } } return rcode; }
static rlm_rcode_t mod_cache_it(void *instance, UNUSED void *thread, REQUEST *request) { rlm_cache_entry_t *c = NULL; rlm_cache_t const *inst = instance; rlm_cache_handle_t *handle; fr_cursor_t cursor; VALUE_PAIR *vp; bool merge = true, insert = true, expire = false, set_ttl = false; int exists = -1; uint8_t buffer[1024]; uint8_t const *key; ssize_t key_len; rlm_rcode_t rcode = RLM_MODULE_NOOP; int ttl = inst->config.ttl; key_len = tmpl_expand((char const **)&key, (char *)buffer, sizeof(buffer), request, inst->config.key, NULL, NULL); if (key_len < 0) return RLM_MODULE_FAIL; if (key_len == 0) { REDEBUG("Zero length key string is invalid"); return RLM_MODULE_INVALID; } /* * If Cache-Status-Only == yes, only return whether we found a * valid cache entry */ vp = fr_pair_find_by_da(request->control, attr_cache_status_only, TAG_ANY); if (vp && vp->vp_bool) { RINDENT(); RDEBUG3("status-only: yes"); REXDENT(); if (cache_acquire(&handle, inst, request) < 0) return RLM_MODULE_FAIL; rcode = cache_find(&c, inst, request, &handle, key, key_len); if (rcode == RLM_MODULE_FAIL) goto finish; rad_assert(!inst->driver->acquire || handle); rcode = c ? RLM_MODULE_OK: RLM_MODULE_NOTFOUND; goto finish; } /* * Figure out what operation we're doing */ vp = fr_pair_find_by_da(request->control, attr_cache_allow_merge, TAG_ANY); if (vp) merge = vp->vp_bool; vp = fr_pair_find_by_da(request->control, attr_cache_allow_insert, TAG_ANY); if (vp) insert = vp->vp_bool; vp = fr_pair_find_by_da(request->control, attr_cache_ttl, TAG_ANY); if (vp) { if (vp->vp_int32 == 0) { expire = true; } else if (vp->vp_int32 < 0) { expire = true; ttl = -(vp->vp_int32); /* Updating the TTL */ } else { set_ttl = true; ttl = vp->vp_int32; } } RINDENT(); RDEBUG3("merge : %s", merge ? "yes" : "no"); RDEBUG3("insert : %s", insert ? "yes" : "no"); RDEBUG3("expire : %s", expire ? "yes" : "no"); RDEBUG3("ttl : %i", ttl); REXDENT(); if (cache_acquire(&handle, inst, request) < 0) return RLM_MODULE_FAIL; /* * Retrieve the cache entry and merge it with the current request * recording whether the entry existed. */ if (merge) { rcode = cache_find(&c, inst, request, &handle, key, key_len); switch (rcode) { case RLM_MODULE_FAIL: goto finish; case RLM_MODULE_OK: rcode = cache_merge(inst, request, c); exists = 1; break; case RLM_MODULE_NOTFOUND: rcode = RLM_MODULE_NOTFOUND; exists = 0; break; default: rad_assert(0); } rad_assert(!inst->driver->acquire || handle); } /* * Expire the entry if told to, and we either don't know whether * it exists, or we know it does. * * We only expire if we're not inserting, as driver insert methods * should perform upserts. */ if (expire && ((exists == -1) || (exists == 1))) { if (!insert) { rad_assert(!set_ttl); switch (cache_expire(inst, request, &handle, key, key_len)) { case RLM_MODULE_FAIL: rcode = RLM_MODULE_FAIL; goto finish; case RLM_MODULE_OK: if (rcode == RLM_MODULE_NOOP) rcode = RLM_MODULE_OK; break; case RLM_MODULE_NOTFOUND: if (rcode == RLM_MODULE_NOOP) rcode = RLM_MODULE_NOTFOUND; break; default: rad_assert(0); break; } /* If it previously existed, it doesn't now */ } /* Otherwise use insert to overwrite */ exists = 0; } /* * If we still don't know whether it exists or not * and we need to do an insert or set_ttl operation * determine that now. */ if ((exists < 0) && (insert || set_ttl)) { switch (cache_find(&c, inst, request, &handle, key, key_len)) { case RLM_MODULE_FAIL: rcode = RLM_MODULE_FAIL; goto finish; case RLM_MODULE_OK: exists = 1; if (rcode != RLM_MODULE_UPDATED) rcode = RLM_MODULE_OK; break; case RLM_MODULE_NOTFOUND: exists = 0; break; default: rad_assert(0); } rad_assert(!inst->driver->acquire || handle); } /* * We can only alter the TTL on an entry if it exists. */ if (set_ttl && (exists == 1)) { rad_assert(c); c->expires = request->packet->timestamp.tv_sec + ttl; switch (cache_set_ttl(inst, request, &handle, c)) { case RLM_MODULE_FAIL: rcode = RLM_MODULE_FAIL; goto finish; case RLM_MODULE_NOTFOUND: case RLM_MODULE_OK: if (rcode != RLM_MODULE_UPDATED) rcode = RLM_MODULE_OK; goto finish; default: rad_assert(0); } } /* * Inserts are upserts, so we don't care about the * entry state, just that we're not meant to be * setting the TTL, which precludes performing an * insert. */ if (insert && (exists == 0)) { switch (cache_insert(inst, request, &handle, key, key_len, ttl)) { case RLM_MODULE_FAIL: rcode = RLM_MODULE_FAIL; goto finish; case RLM_MODULE_OK: if (rcode != RLM_MODULE_UPDATED) rcode = RLM_MODULE_OK; break; case RLM_MODULE_UPDATED: rcode = RLM_MODULE_UPDATED; break; default: rad_assert(0); } rad_assert(!inst->driver->acquire || handle); goto finish; } finish: cache_free(inst, &c); cache_release(inst, request, &handle); /* * Clear control attributes */ for (vp = fr_cursor_init(&cursor, &request->control); vp; vp = fr_cursor_next(&cursor)) { again: if (!fr_dict_attr_is_top_level(vp->da)) continue; switch (vp->da->attr) { case FR_CACHE_TTL: case FR_CACHE_STATUS_ONLY: case FR_CACHE_ALLOW_MERGE: case FR_CACHE_ALLOW_INSERT: case FR_CACHE_MERGE_NEW: RDEBUG2("Removing &control:%s", vp->da->name); vp = fr_cursor_remove(&cursor); talloc_free(vp); vp = fr_cursor_current(&cursor); if (!vp) break; goto again; } } return rcode; }
/* * main */ int main(int argc, char *argv[]) { struct pcap_hdr_s pcap_ghdr; unsigned char ibuf[PKT_SIZE_MAX]; struct pcap_pkt *pkt = (struct pcap_pkt *)&ibuf[0]; int ret, pkt_count = 0; FILE *ifp, *ofp = NULL; char fname[0xFF]; struct anon_keys anon; u_int16_t ethtype; strcpy(anon.passphase, "hoge"); if (argc != 2) { pr_err("Usage: ./pcappriv ./recv.pcap: argc=%d", argc); exit(EXIT_FAILURE); } ifp = fopen(argv[1], "rb"); if (ifp == NULL) { pr_err("cannot open pcap file: %s", argv[1]); exit(EXIT_FAILURE); } // check global pcap header ret = fread(ibuf, sizeof(struct pcap_hdr_s), 1, ifp); if (ret < 1) { pr_err("size of fread is too short: pcap_hdr_s"); exit(EXIT_FAILURE); } set_global_pcaphdr(&pcap_ghdr, (char *)ibuf); if ((pcap_ghdr.magic_number != PCAP_MAGIC) || (pcap_ghdr.version_major != PCAP_VERSION_MAJOR) || (pcap_ghdr.version_minor != PCAP_VERSION_MINOR)) { pr_err("unsupported pcap format:\n" "\tpcap_ghdr.magic_number=%X\n" "\tpcap_ghdr.version_major=%X\n" "\tpcap_ghdr.version_minor=%X", (int)pcap_ghdr.magic_number, (int)pcap_ghdr.version_major, (int)pcap_ghdr.version_minor); goto out; } // create output file strcpy(fname, "output.pcap"); ofp = fopen(fname, "wb"); if (ofp == NULL) { pr_err("cannot create output pcap file."); goto out; } ret = fwrite(&pcap_ghdr, sizeof(struct pcap_hdr_s), 1, ofp); if (ret < 1) { pr_err("cannot write ghdr."); goto out; } anon_init(&anon); cache_init(); set_signal(SIGINT); while (1) { // read pcap header ret = fread(ibuf, sizeof(struct pcaprec_hdr_s), 1, ifp); if (ret < 1) { pr_debug("size of fread is too short: pcaprec_hdr_s"); break; } // checking packet size if ((pkt->pcap.orig_len < PKT_SIZE_MIN) || (pkt->pcap.orig_len > PKT_SIZE_MAX)) { pr_warn("Skip a packet: frame original length=%d", (int)pkt->pcap.orig_len); fseek(ifp, pkt->pcap.incl_len, SEEK_CUR); // skip the packet data continue; } // read packet data ret = fread(ibuf+sizeof(struct pcaprec_hdr_s), pkt->pcap.incl_len, 1, ifp); if (ret < 1) { pr_err("size of fread is too short: pcap data"); break; } INFO_ETH(pkt); ethtype = ntohs(pkt->eth.ether_type); // ipv4 header if (ethtype == ETHERTYPE_IP) { INFO_IP4(pkt_count, &pkt->ip4); anon4(&anon, &pkt->ip4.ip_dst); anon4(&anon, &pkt->ip4.ip_src); // ipv6 header } else if (ethtype == ETHERTYPE_IPV6) { INFO_IP6(pkt_count, &pkt->ip6); anon6(&anon, &pkt->ip6.ip6_dst); anon6(&anon, &pkt->ip6.ip6_src); // ARP //} else if (ethtype == ETHERTYPE_ARP) { // set_arp(&pkt, (char *)ibuf + ETHER_HDR_LEN); // unknown Ethernet Type } else { // temp: debug pr_warn("EtherType: %04X is not supported", ethtype); } // write packet data ret = fwrite(ibuf, sizeof(struct pcaprec_hdr_s) + pkt->pcap.incl_len, 1, ofp); if (ret < 1) { pr_err("cannot write pcap file: packet data"); break; } ++pkt_count; if (caught_signal) break; } out: anon_release(&anon); cache_release(); fclose(ifp); fclose(ofp); return 0; }
static ssize_t cache_xlat(void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace) { rlm_cache_entry_t *c = NULL; rlm_cache_t *inst = instance; rlm_cache_handle_t *handle = NULL; size_t slen; ssize_t ret = 0; vp_tmpl_t target; vp_map_t *map = NULL; slen = tmpl_from_attr_substr(&target, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false); if (slen <= 0) { REDEBUG("%s", fr_strerror()); return -1; } if (cache_acquire(&handle, inst, request) < 0) return -1; switch (cache_find(&c, inst, request, handle, fmt)) { case RLM_MODULE_OK: /* found */ break; case RLM_MODULE_NOTFOUND: /* not found */ *out = '\0'; return 0; default: return -1; } for (map = c->maps; map; map = map->next) { if ((map->lhs->tmpl_da != target.tmpl_da) || (map->lhs->tmpl_tag != target.tmpl_tag) || (map->lhs->tmpl_list != target.tmpl_list)) continue; ret = value_data_prints(out, freespace, map->rhs->tmpl_data_type, map->lhs->tmpl_da, &map->rhs->tmpl_data_value, '\0'); if (is_truncated(slen, freespace)) { REDEBUG("Insufficient buffer space to write cached value"); ret = -1; goto finish; } break; } /* * Check if we found a matching map */ if (!map) { *out = '\0'; return 0; } finish: cache_free(inst, &c); cache_release(inst, request, &handle); return ret; }