/** @brief API to look for a TCP stream identified by 'tuple5' **/ pntoh_tcp_stream_t ntoh_tcp_find_stream ( pntoh_tcp_session_t session , pntoh_tcp_tuple5_t tuple5 ) { ntoh_tcp_key_t key = 0; ntoh_tcp_tuple5_t tuplerev = {0}; pntoh_tcp_stream_t ret = 0; if ( !session || !tuple5 ) return ret; key = tcp_getkey( session , tuple5 ); lock_access( &session->lock ); if ( ! ( ret = (pntoh_tcp_stream_t) htable_find ( session->streams , key , 0) ) ) { tuplerev.destination = tuple5->source; tuplerev.source = tuple5->destination; tuplerev.sport = tuple5->dport; tuplerev.dport = tuple5->sport; tuplerev.protocol = tuple5->protocol; key = tcp_getkey( session , &tuplerev ); ret = (pntoh_tcp_stream_t) htable_find ( session->streams , key , 0); } unlock_access( &session->lock ); return ret; }
/** @brief Remove the stream from the session streams hash table, and notify the user **/ inline static void delete_stream ( pntoh_tcp_session_t session , pntoh_tcp_stream_t *stream , int reason , int extra ) { pntoh_tcp_stream_t item = 0; if ( !stream || !(*stream) ) return; item = *stream; if ( session->streams != 0 ) { if ( htable_find ( session->streams, item->key, 0 ) != 0 ) { htable_remove ( session->streams , item->key, 0); sem_post ( &session->max_streams ); } } if ( session->timewait != 0 ) { if ( htable_find ( session->timewait, item->key, 0 ) != 0 ) { htable_remove ( session->timewait , item->key, 0 ); sem_post ( &session->max_timewait ); } } switch ( extra ) { case NTOH_MAX_SYN_RETRIES_REACHED: extra = NTOH_REASON_MAX_SYN_RETRIES_REACHED; break; case NTOH_MAX_SYNACK_RETRIES_REACHED: extra = NTOH_REASON_MAX_SYNACK_RETRIES_REACHED; break; case NTOH_HANDSHAKE_FAILED: extra = NTOH_REASON_HSFAILED; break; } if ( item->client.receive ) ((pntoh_tcp_callback_t)item->function)(item,&item->client, &item->server,0, reason , extra ); free_lockaccess ( &item->lock ); free ( item ); *stream = 0; return; }
static void smtpd_peer_from_pass_attr(SMTPD_STATE *state) { HTABLE *attr = (HTABLE *) vstream_context(state->client); const char *cp; /* * Extract the client endpoint information from the attribute hash. */ if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0) msg_fatal("missing client address from proxy"); if (strrchr(cp, ':') != 0) { if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0) msg_fatal("bad IPv6 client address syntax from proxy: %s", cp); state->addr = mystrdup(cp); state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0); state->addr_family = AF_INET6; } else { if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0) msg_fatal("bad IPv4 client address syntax from proxy: %s", cp); state->addr = mystrdup(cp); state->rfc_addr = mystrdup(cp); state->addr_family = AF_INET; } if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0) msg_fatal("missing client port from proxy"); if (valid_hostport(cp, DO_GRIPE) == 0) msg_fatal("bad TCP client port number syntax from proxy: %s", cp); state->port = mystrdup(cp); /* * The Dovecot authentication server needs the server IP address. */ if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0) msg_fatal("missing server address from proxy"); if (valid_hostaddr(cp, DO_GRIPE) == 0) msg_fatal("bad IPv6 server address syntax from proxy: %s", cp); state->dest_addr = mystrdup(cp); if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_PORT)) == 0) msg_fatal("missing server port from proxy"); if (valid_hostport(cp, DO_GRIPE) == 0) msg_fatal("bad TCP server port number syntax from proxy: %s", cp); state->dest_port = mystrdup(cp); /* * Convert the client address from string to binary form. */ smtpd_peer_hostaddr_to_sockaddr(state); }
static void anvil_remote_disconnect(VSTREAM *client_stream, const char *ident) { ANVIL_REMOTE *anvil_remote; ANVIL_LOCAL *anvil_local; const char *myname = "anvil_remote_disconnect"; if (msg_verbose) msg_info("%s fd=%d stream=0x%lx ident=%s", myname, vstream_fileno(client_stream), (unsigned long) client_stream, ident); /* * Update local and remote info if this remote connection is listed for * this local server. */ if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) != 0 && (anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) != 0 && ANVIL_LOCAL_REMOTE_LINKED(anvil_local, anvil_remote)) { ANVIL_REMOTE_DROP_ONE(anvil_remote); ANVIL_LOCAL_DROP_ONE(anvil_local, anvil_remote); } if (msg_verbose) msg_info("%s: anvil_local 0x%lx", myname, (unsigned long) anvil_local); /* * Respond to the local server. */ attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_END); }
static void anvil_remote_newtls_stat(VSTREAM *client_stream, const char *ident) { ANVIL_REMOTE *anvil_remote; int rate; /* * Be prepared for "postfix reload" after "connect". */ if ((anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) { rate = 0; } /* * Do not report stale information. */ else { if (anvil_remote->start != 0 && anvil_remote->start + var_anvil_time_unit < event_time()) ANVIL_REMOTE_RSET_RATE(anvil_remote, 0); rate = anvil_remote->ntls; } /* * Respond to local server. */ attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate, ATTR_TYPE_END); }
static void anvil_remote_newtls(VSTREAM *client_stream, const char *ident) { ANVIL_REMOTE *anvil_remote; /* * Be prepared for "postfix reload" after "connect". */ if ((anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) anvil_remote = anvil_remote_conn_update(client_stream, ident); /* * Update newtls rate and respond to local server. */ ANVIL_REMOTE_INCR_NTLS(anvil_remote); attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->ntls, ATTR_TYPE_END); /* * Update peak statistics. */ if (anvil_remote->ntls > max_ntls_rate.value) ANVIL_MAX_UPDATE(max_ntls_rate, anvil_remote->ntls, anvil_remote->ident); }
DICT *dict_open3(const char *dict_type, const char *dict_name, int open_flags, int dict_flags) { const char *myname = "dict_open"; DICT_OPEN_INFO *dp; DICT *dict; if (*dict_type == 0 || *dict_name == 0) msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"", dict_type, dict_name); if (dict_open_hash == 0) dict_open_init(); if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "unsupported dictionary type: %s", dict_type)); if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "cannot open %s:%s: %m", dict_type, dict_name)); if (msg_verbose) msg_info("%s: %s:%s", myname, dict_type, dict_name); /* XXX the choice between wait-for-lock or no-wait is hard-coded. */ if (dict_flags & DICT_FLAG_OPEN_LOCK) { if (dict_flags & DICT_FLAG_LOCK) msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock", myname, dict_type, dict_name); if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0) msg_fatal("%s:%s: unable to get exclusive lock: %m", dict_type, dict_name); } return (dict); }
int psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name, int dnsbl_index) { const char *myname = "psc_dnsbl_retrieve"; PSC_DNSBL_SCORE *score; int result_score; /* * Sanity check. */ if ((score = (PSC_DNSBL_SCORE *) htable_find(dnsbl_score_cache, client_addr)) == 0) msg_panic("%s: no blocklist score for %s", myname, client_addr); /* * Disable callbacks. */ PSC_CALL_BACK_CANCEL(score, dnsbl_index); /* * Reads are destructive. */ result_score = score->total; *dnsbl_name = score->dnsbl_name; score->refcount -= 1; if (score->refcount < 1) { if (msg_verbose > 1) msg_info("%s: delete blocklist score for %s", myname, client_addr); htable_delete(dnsbl_score_cache, client_addr, myfree); } return (result_score); }
static void show_parameters(int mode, char **names) { HTABLE_INFO **list; HTABLE_INFO **ht; char **namep; char *value; /* * Show all parameters. */ if (*names == 0) { list = htable_list(param_table); qsort((char *) list, param_table->used, sizeof(*list), comp_names); for (ht = list; *ht; ht++) print_parameter(mode, ht[0]->value); myfree((char *) list); return; } /* * Show named parameters. */ for (namep = names; *namep; namep++) { if ((value = htable_find(param_table, *namep)) == 0) { msg_warn("%s: unknown parameter", *namep); } else { print_parameter(mode, value); } } }
static void run_test(HTable* htable) { int i, j; /* fill table */ for(i = 1; i <= N; i++) { for(j = 1; j <= N; j++) { bool isNewNode; ExpressionTableNodeData new_node_data; sprintf(new_node_data.expression, "%d + %d", i, j); new_node_data.value = (i + j); htable_insert(htable, (HTableNode*)&new_node_data, &isNewNode); assert(isNewNode); } } assert(htable_nitems(htable) == (N*N)); /* check hash table is filled right */ for(i = 1; i <= N; i++) { for(j = 1; j <= N; j++) { ExpressionTableNode found_node; ExpressionTableNodeData query; sprintf(query.expression, "%d + %d", i, j); found_node = (ExpressionTableNode)htable_find(htable, (HTableNode*)&query); assert(found_node != NULL); assert(found_node->value == (i + j)); } } /* try to delete a non-existing node */ { bool result; ExpressionTableNodeData query; sprintf(query.expression, "ololo trololo"); result = htable_delete(htable, (HTableNode*)&query); assert(result == false); } /* clean table */ for(i = 1; i <= N; i++) { for(j = 1; j <= N; j++) { bool result; ExpressionTableNodeData query; sprintf(query.expression, "%d + %d", i, j); result = htable_delete(htable, (HTableNode*)&query); assert(result == true); } } assert(htable_nitems(htable) == 0); }
int forward_append(DELIVER_ATTR attr) { FORWARD_INFO *info; HTABLE *table_snd; /* * Sanity checks. */ if (msg_verbose) msg_info("forward delivered=%s sender=%s recip=%s", attr.delivered, attr.sender, attr.rcpt.address); if (forward_dt == 0) msg_panic("forward_append: missing forward_init call"); /* * In order to find the recipient list, first index a table by * delivered-to header address, then by envelope sender address. */ if ((table_snd = (HTABLE *) htable_find(forward_dt, attr.delivered)) == 0) { table_snd = htable_create(0); htable_enter(forward_dt, attr.delivered, (void *) table_snd); } if ((info = (FORWARD_INFO *) htable_find(table_snd, attr.sender)) == 0) { if ((info = forward_open(attr.request, attr.sender)) == 0) return (-1); htable_enter(table_snd, attr.sender, (void *) info); } /* * Append the recipient to the message envelope. Don't send the original * recipient or notification mask if it was reset due to mailing list * expansion. */ if (*attr.rcpt.dsn_orcpt) rec_fprintf(info->cleanup, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_DSN_ORCPT, attr.rcpt.dsn_orcpt); if (attr.rcpt.dsn_notify) rec_fprintf(info->cleanup, REC_TYPE_ATTR, "%s=%d", MAIL_ATTR_DSN_NOTIFY, attr.rcpt.dsn_notify); if (*attr.rcpt.orig_addr) rec_fputs(info->cleanup, REC_TYPE_ORCP, attr.rcpt.orig_addr); rec_fputs(info->cleanup, REC_TYPE_RCPT, attr.rcpt.address); return (vstream_ferror(info->cleanup)); }
DICT *dict_open3(const char *dict_type, const char *dict_name, int open_flags, int dict_flags) { const char *myname = "dict_open"; DICT_OPEN_INFO *dp; DICT_OPEN_FN open_fn; DICT *dict; if (*dict_type == 0 || *dict_name == 0) msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"", dict_type, dict_name); if (dict_open_hash == 0) dict_open_init(); if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) { if (dict_open_extend_hook != 0 && (open_fn = dict_open_extend_hook(dict_type)) != 0) { dict_open_register(dict_type, open_fn); dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type); } if (dp == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "unsupported dictionary type: %s", dict_type)); } if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags, "cannot open %s:%s: %m", dict_type, dict_name)); if (msg_verbose) msg_info("%s: %s:%s", myname, dict_type, dict_name); /* XXX The choice between wait-for-lock or no-wait is hard-coded. */ if (dict->flags & DICT_FLAG_OPEN_LOCK) { if (dict->flags & DICT_FLAG_LOCK) msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock", myname, dict_type, dict_name); /* Multi-writer safe map: downgrade persistent lock to temporary. */ if (dict->flags & DICT_FLAG_MULTI_WRITER) { dict->flags &= ~DICT_FLAG_OPEN_LOCK; dict->flags |= DICT_FLAG_LOCK; } /* Multi-writer unsafe map: acquire exclusive lock or bust. */ else if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0) msg_fatal("%s:%s: unable to get exclusive lock: %m", dict_type, dict_name); } return (dict); }
QMGR_TRANSPORT *qmgr_transport_create(const char *name) { QMGR_TRANSPORT *transport; if (htable_find(qmgr_transport_byname, name) != 0) msg_panic("qmgr_transport_create: transport exists: %s", name); transport = (QMGR_TRANSPORT *) mymalloc(sizeof(QMGR_TRANSPORT)); transport->flags = 0; transport->pending = 0; transport->name = mystrdup(name); /* * Use global configuration settings or transport-specific settings. */ transport->dest_concurrency_limit = get_mail_conf_int2(name, _DEST_CON_LIMIT, var_dest_con_limit, 0, 0); transport->recipient_limit = get_mail_conf_int2(name, _DEST_RCPT_LIMIT, var_dest_rcpt_limit, 0, 0); transport->init_dest_concurrency = get_mail_conf_int2(name, _INIT_DEST_CON, var_init_dest_concurrency, 1, 0); transport->xport_rate_delay = get_mail_conf_time2(name, _XPORT_RATE_DELAY, var_xport_rate_delay, 's', 0, 0); transport->rate_delay = get_mail_conf_time2(name, _DEST_RATE_DELAY, var_dest_rate_delay, 's', 0, 0); if (transport->rate_delay > 0) transport->dest_concurrency_limit = 1; if (transport->dest_concurrency_limit != 0 && transport->dest_concurrency_limit < transport->init_dest_concurrency) transport->init_dest_concurrency = transport->dest_concurrency_limit; transport->queue_byname = htable_create(0); QMGR_LIST_INIT(transport->queue_list); transport->dsn = 0; qmgr_feedback_init(&transport->pos_feedback, name, _CONC_POS_FDBACK, VAR_CONC_POS_FDBACK, var_conc_pos_feedback); qmgr_feedback_init(&transport->neg_feedback, name, _CONC_NEG_FDBACK, VAR_CONC_NEG_FDBACK, var_conc_neg_feedback); transport->fail_cohort_limit = get_mail_conf_int2(name, _CONC_COHORT_LIM, var_conc_cohort_limit, 0, 0); if (qmgr_transport_byname == 0) qmgr_transport_byname = htable_create(10); htable_enter(qmgr_transport_byname, name, (void *) transport); QMGR_LIST_APPEND(qmgr_transport_list, transport); if (msg_verbose) msg_info("qmgr_transport_create: %s concurrency %d recipients %d", transport->name, transport->dest_concurrency_limit, transport->recipient_limit); return (transport); }
DICT *dict_open3(const char *dict_type, const char *dict_name, int open_flags, int dict_flags) { const char *myname = "dict_open"; DICT_OPEN_INFO *dp; DICT *dict; if (*dict_type == 0 || *dict_name == 0) msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"", dict_type, dict_name); if (dict_open_hash == 0) dict_open_init(); if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) { #ifdef NO_DYNAMIC_MAPS msg_fatal("%s: unsupported dictionary type: %s", myname, dict_type); #else struct stat st; LIB_FN fn[2]; DICT *(*open) (const char *, int, int); DLINFO *dl=dict_open_dlfind(dict_type); if (!dl) msg_fatal("%s: unsupported dictionary type: %s: Is the postfix-%s package installed?", myname, dict_type, dict_type); if (stat(dl->soname,&st) < 0) { msg_fatal("%s: unsupported dictionary type: %s (%s not found. Is the postfix-%s package installed?)", myname, dict_type, dl->soname, dict_type); } fn[0].name = dl->openfunc; fn[0].ptr = (void**)&open; fn[1].name = NULL; load_library_symbols(dl->soname, fn, NULL); dict_open_register(dict_type, open); dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type); #endif } if (msg_verbose>1) { msg_info("%s: calling %s open routine",myname,dict_type); } if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0) msg_fatal("opening %s:%s %m", dict_type, dict_name); if (msg_verbose) msg_info("%s: %s:%s", myname, dict_type, dict_name); return (dict); }
//First ensure the search name, if it has a cname, search the cname //If we find it in fwd table, return the ip length, it's > 0 //Here we dont care the cname in fwd table, if somebody want to do this //Add the main domain in fwd table int pre_find(struct qoutinfo *qo,struct htable *fwd,struct htable *ht,uchar *ip) { uchar td[512] = {0},*itor = NULL; int xlen = 0,dbg = 100; uchar buffer[2000] = {0}; struct mvalue *mv = NULL; qo->qname = Q_DOMAIN; //default if(qo->hascname == 1) { qo->qing = qo->qbuffer; //latest cname memcpy(td + 1,qo->qbuffer,strlen(qo->qbuffer) + 1); } else { memcpy(td,qo->td,qo->dlen + 1); qo->qing = qo->td + 1; } td[0] = A; //forward ip xlen = htable_find(fwd,td,ip,1900,NULL); //100 for struct mvalue if(xlen > 0) { ip = ip + xlen; mv = (struct mvalue*)ip; mv->num = 0; //tail 0 mv->ttl = 0; mv->hits = 0; mv->len = 0; return xlen; } if(qo->td[0] == CNAME) //query cname return 0; //find nothing td[0] = CNAME; itor = buffer; while(1) //find cname { xlen = find_record_with_ttl(ht,td,itor,2000,NULL); if(xlen > 0) {//if domain has a cname, put it in qo->qbuffer qo->qname = Q_CNAME; qo->hascname = 1; mv = (struct mvalue*)itor; itor = itor + sizeof(struct mvalue); memcpy(td + 1,itor,mv->len); if(mv->len > (QBUFFER_SIZE - 1)) return -1; memcpy(qo->qbuffer,itor,mv->len); qo->qing = qo->qbuffer; } else break; if((dbg --) == 0) return -1; } return 0; }
static QMGR_JOB *qmgr_job_find(QMGR_MESSAGE *message, QMGR_TRANSPORT *transport) { /* * Instead of traversing the message job list, we use single per * transport hash table. This is better (at least with respect to memory * usage) than having single hash table (usually almost empty) for each * message. */ return ((QMGR_JOB *) htable_find(transport->job_byname, message->queue_id)); }
static const char *dict_ht_lookup(DICT *dict, const char *name) { DICT_HT *dict_ht = (DICT_HT *) dict; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name)); }
void dict_open_register(const char *type, DICT_OPEN_FN open) { const char *myname = "dict_open_register"; DICT_OPEN_INFO *dp; HTABLE_INFO *ht; if (dict_open_hash == 0) dict_open_init(); if (htable_find(dict_open_hash, type)) msg_panic("%s: dictionary type exists: %s", myname, type); dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp)); dp->open = open; ht = htable_enter(dict_open_hash, type, (char *) dp); dp->type = ht->key; }
void dict_open_register(const char *type, DICT *(*open) (const char *, int, int)) { const char *myname = "dict_open_register"; DICT_OPEN_INFO *dp; if (dict_open_hash == 0) dict_open_init(); if (htable_find(dict_open_hash, type)) msg_panic("%s: dictionary type exists: %s", myname, type); dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp)); dp->type = mystrdup(type); dp->open = open; htable_enter(dict_open_hash, dp->type, (char *) dp); }
void mkmap_open_register(const char *type, MKMAP_OPEN_FN open_fn) { static const char myname[] = "mkmap_open_register"; MKMAP_OPEN_INFO *mp; HTABLE_INFO *ht; if (mkmap_open_hash == 0) mkmap_open_init(); if (htable_find(mkmap_open_hash, type)) msg_panic("%s: database type exists: %s", myname, type); mp = (MKMAP_OPEN_INFO *) mymalloc(sizeof(*mp)); mp->before_open = open_fn; ht = htable_enter(mkmap_open_hash, type, (char *) mp); mp->type = ht->key; }
int tls_mgr_lookup(const char *unused_type, const char *key, VSTRING *buf) { VSTRING *s; if (tls_cache == 0) return TLS_MGR_STAT_ERR; if ((s = (VSTRING *) htable_find(tls_cache, key)) == 0) return TLS_MGR_STAT_ERR; vstring_memcpy(buf, vstring_str(s), VSTRING_LEN(s)); ++cache_hits; return (TLS_MGR_STAT_OK); }
static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char *ident) { ANVIL_REMOTE *anvil_remote; ANVIL_LOCAL *anvil_local; const char *myname = "anvil_remote_conn_update"; if (msg_verbose) msg_info("%s fd=%d stream=0x%lx ident=%s", myname, vstream_fileno(client_stream), (unsigned long) client_stream, ident); /* * Look up remote connection count information. Update remote connection * rate information. Simply reset the counter every var_anvil_time_unit * seconds. This is easier than maintaining a moving average and it gives * a quicker response to tresspassers. */ if ((anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) { anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote)); ANVIL_REMOTE_FIRST_CONN(anvil_remote, ident); htable_enter(anvil_remote_map, ident, (char *) anvil_remote); if (max_cache_size < anvil_remote_map->used) { max_cache_size = anvil_remote_map->used; max_cache_time = event_time(); } } else { ANVIL_REMOTE_NEXT_CONN(anvil_remote); } /* * Record this connection under the local server information, so that we * can clean up all its connection state when the local server goes away. */ if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) == 0) { anvil_local = (ANVIL_LOCAL *) mymalloc(sizeof(*anvil_local)); ANVIL_LOCAL_INIT(anvil_local); vstream_control(client_stream, VSTREAM_CTL_CONTEXT, (void *) anvil_local, VSTREAM_CTL_END); } ANVIL_LOCAL_ADD_ONE(anvil_local, anvil_remote); if (msg_verbose) msg_info("%s: anvil_local 0x%lx", myname, (unsigned long) anvil_local); return (anvil_remote); }
int mypwnam_err(const char *name, struct mypasswd ** result) { struct passwd *pwd; struct mypasswd *mypwd; /* * See if this is the same user as last time. */ if (last_pwd != 0) { if (strcmp(last_pwd->pw_name, name) != 0) { mypwfree(last_pwd); last_pwd = 0; } else { *result = mypwd = last_pwd; mypwd->refcount++; return (0); } } /* * Find the info in the cache or in the password database. */ if ((mypwd = (struct mypasswd *) htable_find(mypwcache_name, name)) == 0) { #ifdef HAVE_POSIX_GETPW_R char pwstore[GETPW_R_BUFSIZ]; struct passwd pwbuf; int err; err = getpwnam_r(name, &pwbuf, pwstore, sizeof(pwstore), &pwd); if (err != 0) return (err); if (pwd == 0) { *result = 0; return (0); } #else if ((pwd = getpwnam(name)) == 0) { *result = 0; return (0); } #endif mypwd = mypwenter(pwd); } *result = last_pwd = mypwd; mypwd->refcount += 2; return (0); }
int find_record_with_ttl(struct htable *ht, uchar * key, int klen, int type, uchar *val, int vlen, struct mvalue *md, hashval_t *hash) { int idx, ret; uchar *oval; idx = get_pre_mem_hash(key, klen, hash); ret = htable_find(ht + idx, key, klen, type, val, vlen, md, hash); if (ret > 0) { if (ttl_expired(val) == 1) { oval = htable_delete(ht + idx, key, klen, type, *hash); if (oval != NULL) free(oval); } else { return ret; } } return -1; }
int psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name, int dnsbl_index, int *dnsbl_ttl) { const char *myname = "psc_dnsbl_retrieve"; PSC_DNSBL_SCORE *score; int result_score; int result_ttl; /* * Sanity check. */ if ((score = (PSC_DNSBL_SCORE *) htable_find(dnsbl_score_cache, client_addr)) == 0) msg_panic("%s: no blocklist score for %s", myname, client_addr); /* * Disable callbacks. */ PSC_CALL_BACK_CANCEL(score, dnsbl_index); /* * Reads are destructive. */ result_score = score->total; *dnsbl_name = score->dnsbl_name; result_ttl = (result_score > 0) ? score->fail_ttl : score->pass_ttl; /* As with dnsblog(8), a value < 0 means no reply TTL. */ if (result_ttl < var_psc_dnsbl_min_ttl) result_ttl = var_psc_dnsbl_min_ttl; if (result_ttl > var_psc_dnsbl_max_ttl) result_ttl = var_psc_dnsbl_max_ttl; *dnsbl_ttl = result_ttl; if (msg_verbose) msg_info("%s: addr=%s score=%d ttl=%d", myname, client_addr, result_score, result_ttl); score->refcount -= 1; if (score->refcount < 1) { if (msg_verbose > 1) msg_info("%s: delete blocklist score for %s", myname, client_addr); htable_delete(dnsbl_score_cache, client_addr, myfree); } return (result_score); }
static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident) { ANVIL_REMOTE *anvil_remote; const char *myname = "anvil_remote_lookup"; if (msg_verbose) msg_info("%s fd=%d stream=0x%lx ident=%s", myname, vstream_fileno(client_stream), (unsigned long) client_stream, ident); /* * Look up remote client information. */ if ((anvil_remote = (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) { attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_INT, ANVIL_ATTR_COUNT, 0, ATTR_TYPE_INT, ANVIL_ATTR_RATE, 0, ATTR_TYPE_INT, ANVIL_ATTR_MAIL, 0, ATTR_TYPE_INT, ANVIL_ATTR_RCPT, 0, ATTR_TYPE_INT, ANVIL_ATTR_NTLS, 0, ATTR_TYPE_END); } else { /* * Do not report stale information. */ if (anvil_remote->start != 0 && anvil_remote->start + var_anvil_time_unit < event_time()) ANVIL_REMOTE_RSET_RATE(anvil_remote, 0); attr_print_plain(client_stream, ATTR_FLAG_NONE, ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK, ATTR_TYPE_INT, ANVIL_ATTR_COUNT, anvil_remote->count, ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->rate, ATTR_TYPE_INT, ANVIL_ATTR_MAIL, anvil_remote->mail, ATTR_TYPE_INT, ANVIL_ATTR_RCPT, anvil_remote->rcpt, ATTR_TYPE_INT, ANVIL_ATTR_NTLS, anvil_remote->ntls, ATTR_TYPE_END); } }
static const char *dict_thash_lookup(DICT *dict, const char *name) { DICT_THASH *dict_thash = (DICT_THASH *) dict; const char *result = 0; /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_FIX) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(10); vstring_strcpy(dict->fold_buf, name); name = lowercase(vstring_str(dict->fold_buf)); } /* * Look up the value. */ result = htable_find(dict_thash->table, name); DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, result); }
const HEADER_OPTS *header_opts_find(const char *string) { const char *cp; if (header_hash == 0) header_opts_init(); /* * Look up the lower-cased version of the header name. */ VSTRING_RESET(header_key); for (cp = string; *cp != ':'; cp++) { if (*cp == 0) msg_panic("header_opts_find: no colon in header: %.30s", string); VSTRING_ADDCH(header_key, TOLOWER(*cp)); } vstring_truncate(header_key, trimblanks(vstring_str(header_key), cp - string) - vstring_str(header_key)); VSTRING_TERMINATE(header_key); return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key))); }
QMGR_QUEUE *qmgr_queue_find(QMGR_TRANSPORT *transport, const char *name) { return ((QMGR_QUEUE *) htable_find(transport->queue_byname, name)); }
MKMAP *mkmap_open(const char *type, const char *path, int open_flags, int dict_flags) { MKMAP *mkmap; const MKMAP_OPEN_INFO *mp; MKMAP_OPEN_FN open_fn; /* * Find out what map type to use. */ if (mkmap_open_hash == 0) mkmap_open_init(); if ((mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type)) == 0) { if (mkmap_open_extend_hook != 0 && (open_fn = mkmap_open_extend_hook(type)) != 0) { mkmap_open_register(type, open_fn); mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type); } if (mp == 0) msg_fatal("unsupported map type for this operation: %s", type); } if (msg_verbose) msg_info("open %s %s", type, path); /* * Do whatever before-open initialization is needed, such as acquiring a * global exclusive lock on an existing database file. Individual Postfix * dict modules implement locking only for individual record operations, * because most Postfix applications don't need global exclusive locks. */ mkmap = mp->before_open(path); /* * Delay signal delivery, so that we won't leave the database in an * inconsistent state if we can avoid it. */ sigdelay(); /* * Truncate the database upon open, and update it. Read-write mode is * needed because the underlying routines read as well as write. We * explicitly clobber lock_fd to trigger a fatal error when a map wants * to unlock the database after individual transactions: that would * result in race condition problems. We clobbber stat_fd as well, * because that, too, is used only for individual-transaction clients. */ mkmap->dict = mkmap->open(path, open_flags, dict_flags); mkmap->dict->lock_fd = -1; /* XXX just in case */ mkmap->dict->stat_fd = -1; /* XXX just in case */ mkmap->dict->flags |= DICT_FLAG_DUP_WARN; mkmap->multi_writer = (mkmap->dict->flags & DICT_FLAG_MULTI_WRITER); /* * Do whatever post-open initialization is needed, such as acquiring a * global exclusive lock on a database file that did not exist. * Individual Postfix dict modules implement locking only for individual * record operations, because most Postfix applications don't need global * exclusive locks. */ if (mkmap->after_open) mkmap->after_open(mkmap); /* * Resume signal delivery if multi-writer safe. */ if (mkmap->multi_writer) sigresume(); return (mkmap); }