⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 2 页
字号:
#if 1void for_each_state(void *(f)(struct state *, void *data), void *data){	struct state *st, *ocs = cur_state;	int i;	for (i=0; i<STATE_TABLE_SIZE; i++) {		for (st = statetable[i]; st != NULL; st = st->st_hashchain_next) {			set_cur_state(st);			f(st, data);		}	}	cur_state = ocs;}#endif/* * Find a state object. */struct state *find_state(const u_char *icookie, const u_char *rcookie, const ip_address *peer, msgid_t /*network order*/ msgid){    struct state *st = *state_hash(icookie, rcookie, peer);    while (st != (struct state *) NULL)    {	if (sameaddr(peer, &st->st_connection->spd.that.host_addr)	    && memcmp(icookie, st->st_icookie, COOKIE_SIZE) == 0	    && memcmp(rcookie, st->st_rcookie, COOKIE_SIZE) == 0)	{	    DBG(DBG_CONTROL,		DBG_log("peer and cookies match on #%ld, provided msgid %08x vs %08x"			, st->st_serialno			, ntohl(msgid), ntohl(st->st_msgid)));	    if(msgid == st->st_msgid)		break;#if 0	    if(msgid == st->st_msgid2)	    {		u_char tmpiv[MAX_DIGEST_LEN];		/* oh, damn, life is bad, they reused the old one */		openswan_log("find_state: old message id %08x reused, Coping."			      , msgid);				/* swap msgid/msgid2 and the IVs */		/* msgid already == st->st_msgid2 */		st->st_msgid2 = st->st_msgid;		st->st_msgid = msgid;				save_iv(st, tmpiv);		set_iv(st, st->st_old_iv);		memcpy(st->st_old_iv, tmpiv, MAX_DIGEST_LEN);		break;	    }#endif	}	st = st->st_hashchain_next;    }    DBG(DBG_CONTROL,	if (st == NULL)	    DBG_log("state object not found");	else	    DBG_log("state object #%lu found, in %s"		, st->st_serialno		, enum_show(&state_names, st->st_state)));    return st;}/* * Find a state object. */struct state *find_info_state(const u_char *icookie		, const u_char *rcookie		, const ip_address *peer		, msgid_t /*network order*/ msgid){    struct state *st = *state_hash(icookie, rcookie, peer);    int i;    bool found = FALSE;    struct state *best = NULL;    for(;st != (struct state *) NULL;	st = st->st_hashchain_next)    {	if (sameaddr(peer, &st->st_connection->spd.that.host_addr)	    && memcmp(icookie, st->st_icookie, COOKIE_SIZE) == 0	    && memcmp(rcookie, st->st_rcookie, COOKIE_SIZE) == 0)	{	    DBG(DBG_CONTROL,		DBG_log("peer and cookies match on #%ld, provided msgid %08x vs %08x"			, st->st_serialno			, ntohl(msgid), ntohl(st->st_msgid)));	    if(msgid == st->st_msgid)		best = st;                 /* perfect match is best */	    else	    {		found = FALSE;		for(i=0; i < MAX_INFO_EXG && !found; i++)		{		    if(msgid == st->st_infoid[i]) found=TRUE;		    /* need to do something with the IVs, I think */		    /* XXX but not yet */		}		/* only pick this one if there is no better one */		if(found) {		    if(best == NULL) best = st;		}	    }	}    }    DBG(DBG_CONTROL,	if (best == NULL)	    DBG_log("state object not found");	else	    DBG_log("state object #%lu found, in %s"		, best->st_serialno		, enum_show(&state_names, best->st_state)));    return best;}/* Find the state that sent a packet * ??? this could be expensive -- it should be rate-limited to avoid DoS */struct state *find_sender(size_t packet_len, u_char *packet){    int i;    struct state *st;    if (packet_len >= sizeof(struct isakmp_hdr))	for (i = 0; i < STATE_TABLE_SIZE; i++)	    for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)		if (st->st_tpacket.ptr != NULL		&& st->st_tpacket.len == packet_len		&& memcmp(st->st_tpacket.ptr, packet, packet_len) == 0)		    return st;    return NULL;}struct state *find_phase2_state_to_delete(const struct state *p1st, u_int8_t protoid, ipsec_spi_t spi, bool *bogus){    struct state *st;    int i;    *bogus = FALSE;    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	{	    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)	    && p1st->st_connection->host_pair == st->st_connection->host_pair	    && same_peer_ids(p1st->st_connection, st->st_connection, NULL))	    {		struct ipsec_proto_info *pr = protoid == PROTO_IPSEC_AH		    ? &st->st_ah : &st->st_esp;		if (pr->present)		{		    if (pr->attrs.spi == spi)			return st;		    if (pr->our_spi == spi)			*bogus = TRUE;		}	    }	}    }    return NULL;}/* Find newest Phase 1 negotiation state object for suitable for connection c */struct state *find_phase1_state(const struct connection *c, lset_t ok_states){    struct state	*st,	*best = NULL;    int i;    for (i = 0; i < STATE_TABLE_SIZE; i++)	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	    if (LHAS(ok_states, st->st_state)	    && c->host_pair == st->st_connection->host_pair	    && same_peer_ids(c, st->st_connection, NULL)	    && (best == NULL || best->st_serialno < st->st_serialno))		best = st;    return best;}voidstate_eroute_usage(ip_subnet *ours, ip_subnet *his, unsigned long count, time_t nw){    struct state *st;    int i;    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	{	    struct connection *c = st->st_connection;	    /* XXX spd-enum */	    if (IS_IPSEC_SA_ESTABLISHED(st->st_state)		&& c->spd.eroute_owner == st->st_serialno		&& c->spd.routing == RT_ROUTED_TUNNEL		&& samesubnet(&c->spd.this.client, ours)		&& samesubnet(&c->spd.that.client, his))	    {		if (st->st_outbound_count != count)		{		    st->st_outbound_count = count;		    st->st_outbound_time = nw;		}		return;	    }	}    }    DBG(DBG_CONTROL,	{	    char ourst[SUBNETTOT_BUF];	    char hist[SUBNETTOT_BUF];	    subnettot(ours, 0, ourst, sizeof(ourst));	    subnettot(his, 0, hist, sizeof(hist));	    DBG_log("unknown tunnel eroute %s -> %s found in scan"		, ourst, hist);	});}void fmt_state(struct state *st, time_t n, char *state_buf, size_t state_buf_len, char *state_buf2, size_t state_buf2_len){    /* what the heck is interesting about a state? */    const struct connection *c = st->st_connection;    long delta;    char inst[CONN_INST_BUF];    char dpdbuf[128];    const char *np1 = c->newest_isakmp_sa == st->st_serialno	? "; newest ISAKMP" : "";    const char *np2 = c->newest_ipsec_sa == st->st_serialno	? "; newest IPSEC" : "";    /* XXX spd-enum */    const char *eo = c->spd.eroute_owner == st->st_serialno	? "; eroute owner" : "";    fmt_conn_instance(c, inst);    if(st->st_event) {	delta = st->st_event->ev_time >= n	    ? (long)(st->st_event->ev_time - n)	    : -(long)(n - st->st_event->ev_time);    } else {	delta = -1;    }    if (IS_IPSEC_SA_ESTABLISHED(st->st_state))    {	dpdbuf[0]='\0';    } else {	if(st->hidden_variables.st_dpd) {	    time_t n = time(NULL);	    snprintf(dpdbuf, sizeof(dpdbuf), "; lastdpd=%lds(seq in:%u out:%u)"		     , st->st_last_dpd !=0 ? n - st->st_last_dpd : -1		     , st->st_dpd_seqno		     , st->st_dpd_expectseqno);	} else {	    snprintf(dpdbuf, sizeof(dpdbuf), "; nodpd");	}    }	    snprintf(state_buf, state_buf_len	, "#%lu: \"%s\"%s %s (%s); %s in %lds%s%s%s%s"	, st->st_serialno	, c->name, inst	, enum_name(&state_names, st->st_state)	, state_story[st->st_state - STATE_MAIN_R0]	     , st->st_event ? enum_name(&timer_event_names, st->st_event->ev_type) : "none"	, delta	     , np1, np2, eo, dpdbuf);    /* print out SPIs if SAs are established */    if (state_buf2_len != 0)	state_buf2[0] = '\0';	/* default to empty */    if (IS_IPSEC_SA_ESTABLISHED(st->st_state))    {	char lastused[40];	/* should be plenty long enough */	char buf[SATOT_BUF*6 + 1];	char *p = buf;#	define add_said(adst, aspi, aproto) { \	    ip_said s; \	    \	    initsaid(adst, aspi, aproto, &s); \	    if (p < &buf[sizeof(buf)-1]) \	    { \		*p++ = ' '; \		p += satot(&s, 0, p, &buf[sizeof(buf)] - p) - 1; \	    } \	}	/* XXX - mcr last used is really an attribute of the connection */	lastused[0] = '\0';	if (c->spd.eroute_owner == st->st_serialno	&& st->st_outbound_count != 0)	{	    snprintf(lastused, sizeof(lastused)		, " used %lus ago;"		, (unsigned long) (now() - st->st_outbound_time));	}	*p = '\0';	if (st->st_ah.present)	{	    add_said(&c->spd.that.host_addr, st->st_ah.attrs.spi, SA_AH);	    add_said(&c->spd.this.host_addr, st->st_ah.our_spi, SA_AH);	}	if (st->st_esp.present)	{	    add_said(&c->spd.that.host_addr, st->st_esp.attrs.spi, SA_ESP);	    add_said(&c->spd.this.host_addr, st->st_esp.our_spi, SA_ESP);	}	if (st->st_ipcomp.present)	{	    add_said(&c->spd.that.host_addr, st->st_ipcomp.attrs.spi, SA_COMP);	    add_said(&c->spd.this.host_addr, st->st_ipcomp.our_spi, SA_COMP);	}#ifdef KLIPS	if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL	|| st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL	|| st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL)	{	    add_said(&c->spd.that.host_addr, st->st_tunnel_out_spi, SA_IPIP);	    add_said(&c->spd.this.host_addr, st->st_tunnel_in_spi, SA_IPIP);	}#endif	snprintf(state_buf2, state_buf2_len	    , "#%lu: \"%s\"%s%s%s"	    , st->st_serialno	    , c->name, inst	    , lastused	    , buf);#	undef add_said    }}/* * sorting logic is: * *  name *  type *  instance# *  isakmp_sa (XXX probably wrong) * */static intstate_compare(const void *a, const void *b){    const struct state *sap = *(const struct state *const *)a;    struct connection *ca = sap->st_connection;    const struct state *sbp = *(const struct state *const *)b;    struct connection *cb = sbp->st_connection;    /* DBG_log("comparing %s to %s", ca->name, cb->name); */    return connection_compare(ca, cb);}voidshow_states_status(void){    time_t n = now();    int i;    char state_buf[LOG_WIDTH];    char state_buf2[LOG_WIDTH];    int count;    struct state **array;    /* make count of states */    count = 0;    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	struct state *st;	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	{	    count++;	}    }    /* build the array */    array = alloc_bytes(sizeof(struct state *)*count, "state array");    count = 0;    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	struct state *st;	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	{	    array[count++]=st;	}    }    /* sort it! */    qsort(array, count, sizeof(struct state *), state_compare);    /* now print sorted results */    for (i = 0; i < count; i++)    {	struct state *st;	st = array[i];	fmt_state(st, n, state_buf, sizeof(state_buf)		  , state_buf2, sizeof(state_buf2));	whack_log(RC_COMMENT, state_buf);	if (state_buf2[0] != '\0')	    whack_log(RC_COMMENT, state_buf2);	/* show any associated pending Phase 2s */	if (IS_PHASE1(st->st_state))	    show_pending_phase2(st->st_connection->host_pair, st);    }    /* free the array */    pfree(array);}/* Given that we've used up a range of unused CPI's, * search for a new range of currently unused ones. * Note: this is very expensive when not trivial! * If we can't find one easily, choose 0 (a bad SPI, * no matter what order) indicating failure. */voidfind_my_cpi_gap(cpi_t *latest_cpi, cpi_t *first_busy_cpi){    int tries = 0;    cpi_t base = *latest_cpi;    cpi_t closest;    int i;startover:    closest = ~0;	/* not close at all */    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	struct state *st;	for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)	{	    if (st->st_ipcomp.present)	    {		cpi_t c = ntohl(st->st_ipcomp.our_spi) - base;		if (c < closest)		{		    if (c == 0)		    {			/* oops: next spot is occupied; start over */			if (++tries == 20)			{			    /* FAILURE */			    *latest_cpi = *first_busy_cpi = 0;			    return;			}			base++;			if (base > IPCOMP_LAST_NEGOTIATED)			    base = IPCOMP_FIRST_NEGOTIATED;			goto startover;	/* really a tail call */		    }		    closest = c;		}	    }	}    }    *latest_cpi = base;	/* base is first in next free range */    *first_busy_cpi = closest + base;	/* and this is the roof */}/* Muck with high-order 16 bits of this SPI in order to make * the corresponding SAID unique. * Its low-order 16 bits hold a well-known IPCOMP CPI. * Oh, and remember that SPIs are stored in network order. * Kludge!!!  So I name it with the non-English word "uniquify". * If we can't find one easily, return 0 (a bad SPI, * no matter what order) indicating failure. */ipsec_spi_tuniquify_his_cpi(ipsec_spi_t cpi, struct state *st){    int tries = 0;    int i;startover:    /* network order makes first two bytes our target */    get_rnd_bytes((u_char *)&cpi, 2);    /* Make sure that the result is unique.     * Hard work.  If there is no unique value, we'll loop forever!     */    for (i = 0; i < STATE_TABLE_SIZE; i++)    {	struct state *s;	for (s = statetable[i]; s != NULL; s = s->st_hashchain_next)	{	    if (s->st_ipcomp.present	    && sameaddr(&s->st_connection->spd.that.host_addr	      , &st->st_connection->spd.that.host_addr)	    && cpi == s->st_ipcomp.attrs.spi)	    {		if (++tries == 20)		    return 0;	/* FAILURE */		goto startover;	    }	}    }    return cpi;}/*  * Immediately schedule a replace event for all states for a peer. */void replace_states_by_peer(ip_address *peer){    struct state *st = NULL;    int i;    /* struct event *ev;     currently unused */    for (i = 0; st == NULL && i < STATE_TABLE_SIZE; i++)        for (st = statetable[i]; st != NULL; st = st->st_hashchain_next)            /* Only replace if it already has a replace event. */            if (sameaddr(&st->st_connection->spd.that.host_addr, peer)                    && (IS_ISAKMP_SA_ESTABLISHED(st->st_state) || IS_IPSEC_SA_ESTABLISHED(st->st_state))                    && st->st_event->ev_type == EVENT_SA_REPLACE)            {                delete_event(st);                delete_dpd_event(st);                event_schedule(EVENT_SA_REPLACE, 0, st);            }}void copy_quirks(struct isakmp_quirks *dq		 , struct isakmp_quirks *sq){    dq->xauth_ack_msgid   |= sq->xauth_ack_msgid;    dq->modecfg_pull_mode |= sq->modecfg_pull_mode;    dq->nat_traversal_vid |= sq->nat_traversal_vid;}/* * Local Variables: * c-basic-offset:4 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -