? conv ? o ? xx Index: npf_conn.c =================================================================== RCS file: /cvsroot/src/sys/net/npf/npf_conn.c,v retrieving revision 1.16 diff -u -u -r1.16 npf_conn.c --- npf_conn.c 5 Feb 2015 22:04:03 -0000 1.16 +++ npf_conn.c 8 Dec 2016 23:10:04 -0000 @@ -240,6 +240,44 @@ return true; } +static uint32_t +connkey_setkey(npf_connkey_t *key, uint32_t proto, npf_addr_t *ips, + uint16_t *id, size_t alen, bool forw) +{ + uint32_t isrc, idst; + if (__predict_true(forw)) { + isrc = NPF_SRC, idst = NPF_DST; + } else { + isrc = NPF_DST, idst = NPF_SRC; + } + + /* + * Construct a key formed out of 32-bit integers. The key layout: + * + * Field: | proto | alen | src-id | dst-id | src-addr | dst-addr | + * +--------+--------+--------+--------+----------+----------+ + * Bits: | 16 | 16 | 16 | 16 | 32-128 | 32-128 | + * + * The source and destination are inverted if they key is for the + * backwards stream (forw == false). The address length depends + * on the 'alen' field; it is a length in bytes, either 4 or 16. + */ + + key->ck_key[0] = ((uint32_t)proto << 16) | (alen & 0xffff); + key->ck_key[1] = ((uint32_t)id[isrc] << 16) | id[idst]; + + if (__predict_true(alen == sizeof(in_addr_t))) { + key->ck_key[2] = ips[isrc]->s6_addr32[0]; + key->ck_key[3] = ips[idst]->s6_addr32[0]; + return 4 * sizeof(uint32_t); + } else { + const u_int nwords = alen >> 2; + memcpy(&key->ck_key[2], ips[isrc], alen); + memcpy(&key->ck_key[2 + nwords], ips[idst], alen); + return (2 + (nwords * 2)) * sizeof(uint32_t); + } +} + /* * npf_conn_conkey: construct a key for the connection lookup. * @@ -288,40 +326,11 @@ return 0; } - if (__predict_true(forw)) { - isrc = NPF_SRC, idst = NPF_DST; - } else { - isrc = NPF_DST, idst = NPF_SRC; - } - - /* - * Construct a key formed out of 32-bit integers. The key layout: - * - * Field: | proto | alen | src-id | dst-id | src-addr | dst-addr | - * +--------+--------+--------+--------+----------+----------+ - * Bits: | 16 | 16 | 16 | 16 | 32-128 | 32-128 | - * - * The source and destination are inverted if they key is for the - * backwards stream (forw == false). The address length depends - * on the 'alen' field; it is a length in bytes, either 4 or 16. - */ - - key->ck_key[0] = ((uint32_t)npc->npc_proto << 16) | (alen & 0xffff); - key->ck_key[1] = ((uint32_t)id[isrc] << 16) | id[idst]; - - if (__predict_true(alen == sizeof(in_addr_t))) { - key->ck_key[2] = npc->npc_ips[isrc]->s6_addr32[0]; - key->ck_key[3] = npc->npc_ips[idst]->s6_addr32[0]; - keylen = 4 * sizeof(uint32_t); - } else { - const u_int nwords = alen >> 2; - memcpy(&key->ck_key[2], npc->npc_ips[isrc], alen); - memcpy(&key->ck_key[2 + nwords], npc->npc_ips[idst], alen); - keylen = (2 + (nwords * 2)) * sizeof(uint32_t); - } - return keylen; + return connkey_setkey(key, npc->npc_proto, npc->npc_ips, id, alen, + forw); } + static __inline void connkey_set_addr(npf_connkey_t *key, const npf_addr_t *naddr, const int di) { @@ -343,6 +352,26 @@ } /* + * npf_conn_ok: check if the connection is active, and has the right direction. + */ +static bool +npf_conn_ok(npf_conn_t *con, const int di, bool forw) +{ + uint32_t flags = con->c_flags; + + /* Check if connection is active and not expired. */ + bool ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE; + if (__predict_false(!ok)) + return false; + + /* Check if the direction is consistent */ + bool pforw = (flags & PFIL_ALL) == di; + if (__predict_false(forw != pforw)) + return false; + return true; +} + +/* * npf_conn_lookup: lookup if there is an established connection. * * => If found, we will hold a reference for the caller. @@ -353,7 +382,7 @@ const nbuf_t *nbuf = npc->npc_nbuf; npf_conn_t *con; npf_connkey_t key; - u_int flags, cifid; + u_int cifid; bool ok, pforw; /* Construct a key and lookup for a connection in the store. */ @@ -367,9 +396,7 @@ KASSERT(npc->npc_proto == con->c_proto); /* Check if connection is active and not expired. */ - flags = con->c_flags; - ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE; - if (__predict_false(!ok)) { + if (!npf_conn_ok(con, di, forw)) { atomic_dec_uint(&con->c_refcnt); return NULL; } @@ -383,11 +410,6 @@ atomic_dec_uint(&con->c_refcnt); return NULL; } - pforw = (flags & PFIL_ALL) == di; - if (__predict_false(*forw != pforw)) { - atomic_dec_uint(&con->c_refcnt); - return NULL; - } /* Update the last activity time. */ getnanouptime(&con->c_atime); @@ -907,6 +929,59 @@ return cdict; } +static uint32_t +npf_connkey_import(prop_dictionary_t idict, npf_connkey_t *key, uint16_t *dir) +{ + uint16_t proto; + prop_object_t sobj, dobj; + uint16_t id[2]; + npf_addr_t ips[2]; + + prop_dictionary_get_uint16(idict, "proto", &proto); + prop_dictionary_get_uint16(idict, "direction", dir); + + prop_dictionary_get_uint16(idict, "src-id", &id[NPF_SRC]); + prop_dictionary_get_uint16(idict, "dst-id", &id[NPF_DST]); + + sobj = prop_dictionary_get(cdict, "saddr"); + if ((ips[NPF_SRC] = prop_data_data_nocopy(sobj)) == NULL) + return 0; + + dobj = prop_dictionary_get(cdict, "daddr"); + if ((ips[NPF_DST] = prop_data_data_nocopy(dobj)) == NULL) + return 0; + + size_t alen = prop_data_size(sobj); + if (alen != prop_data_size(dobj)) + return 0; + + return connkey_setkey(key, proto, ips, id, alen, true); +} + +prop_dictionary_t +npf_conn_find(prop_dictionary_t idict) +{ + npf_connkey_t key; + uint16_t dir; + + if (!npf_connkey_import(idict, &key, &dir)) + return NULL; + + con = npf_conndb_lookup(conn_db, &key, true); + if (con == NULL) + return NULL; + + if (!npf_conn_ok(con, dir, true)) { + atomic_dec_uint(&con->c_refcnt); + return NULL; + } + + idict = npf_conn_export(con); + atomic_dec_uint(&con->c_refcnt); + + return idict; +} + /* * npf_conn_import: fully reconstruct a single connection from a * directory and insert into the given database.