- fix initial pcb vrf setting when the initial vrf is not the
default_vrf_id - Missing lock/unlock of inp added as well in the v6 side. - IFN hash table moves to sctppcbinfo since indexes are unique across systems (including different VRFs) this makes it easier to do ifn lookups.
This commit is contained in:
parent
e20b748d5f
commit
f4c93d2405
@ -489,7 +489,6 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
|
||||
* Now lets see if we can deliver the next one on
|
||||
* the stream
|
||||
*/
|
||||
uint16_t nxt_todel;
|
||||
struct sctp_stream_in *strm;
|
||||
|
||||
strm = &asoc->strmin[stream_no];
|
||||
|
@ -164,10 +164,9 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
|
||||
#define SCTP_SIZE_OF_VRF_HASH 3
|
||||
#define SCTP_IFNAMSIZ IFNAMSIZ
|
||||
#define SCTP_DEFAULT_VRFID 0
|
||||
#define SCTP_DEFAULT_TABLEID 0
|
||||
#define SCTP_VRF_ADDR_HASH_SIZE 16
|
||||
#define SCTP_VRF_IFN_HASH_SIZE 3
|
||||
#define SCTP_VRF_DEFAULT_TABLEID(vrf_id) 0
|
||||
#define SCTP_INIT_VRF_TABLEID(vrf)
|
||||
|
||||
#define SCTP_IFN_IS_IFT_LOOP(ifn) ((ifn)->ifn_type == IFT_LOOP)
|
||||
|
||||
|
@ -2370,7 +2370,7 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
|
||||
|
||||
ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
|
||||
ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
|
||||
sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
sctp_ifn = sctp_find_ifn(ifn, ifn_index);
|
||||
/*
|
||||
* first question, is the ifn we will emit on in our list, if so, we
|
||||
* want such an address. Note that we first looked for a preferred
|
||||
@ -2478,7 +2478,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
|
||||
ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
|
||||
ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
|
||||
sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
sctp_ifn = sctp_find_ifn(ifn, ifn_index);
|
||||
|
||||
/*
|
||||
* first question, is the ifn we will emit on in our list? If so,
|
||||
@ -2705,7 +2705,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
ifn = SCTP_GET_IFN_VOID_FROM_ROUTE(ro);
|
||||
ifn_index = SCTP_GET_IF_INDEX_FROM_ROUTE(ro);
|
||||
|
||||
emit_ifn = looked_at = sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
emit_ifn = looked_at = sctp_ifn = sctp_find_ifn(ifn, ifn_index);
|
||||
if (sctp_ifn == NULL) {
|
||||
/* ?? We don't have this guy ?? */
|
||||
goto bound_all_plan_b;
|
||||
@ -10572,7 +10572,7 @@ sctp_lower_sosend(struct socket *so,
|
||||
struct thread *p
|
||||
)
|
||||
{
|
||||
unsigned int sndlen, max_len;
|
||||
unsigned int sndlen = 0, max_len;
|
||||
int error, len;
|
||||
struct mbuf *top = NULL;
|
||||
|
||||
@ -11747,6 +11747,7 @@ sctp_lower_sosend(struct socket *so,
|
||||
out:
|
||||
out_unlocked:
|
||||
|
||||
|
||||
if (create_lock_applied) {
|
||||
SCTP_ASOC_CREATE_UNLOCK(inp);
|
||||
create_lock_applied = 0;
|
||||
|
@ -155,6 +155,8 @@ sctp_allocate_vrf(int vrf_id)
|
||||
vrf->vrf_id = vrf_id;
|
||||
LIST_INIT(&vrf->ifnlist);
|
||||
vrf->total_ifa_count = 0;
|
||||
/* now also setup table ids */
|
||||
SCTP_INIT_VRF_TABLEID(vrf);
|
||||
/* Init the HASH of addresses */
|
||||
vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE,
|
||||
&vrf->vrf_addr_hashmark);
|
||||
@ -166,17 +168,6 @@ sctp_allocate_vrf(int vrf_id)
|
||||
SCTP_FREE(vrf, SCTP_M_VRF);
|
||||
return (NULL);
|
||||
}
|
||||
vrf->vrf_ifn_hash = SCTP_HASH_INIT(SCTP_VRF_IFN_HASH_SIZE,
|
||||
&vrf->vrf_ifn_hashmark);
|
||||
if (vrf->vrf_ifn_hash == NULL) {
|
||||
/* No memory */
|
||||
#ifdef INVARIANTS
|
||||
panic("No memory for VRF:%d", vrf_id);
|
||||
#endif
|
||||
SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark);
|
||||
SCTP_FREE(vrf, SCTP_M_VRF);
|
||||
return (NULL);
|
||||
}
|
||||
/* Add it to the hash table */
|
||||
bucket = &sctppcbinfo.sctp_vrfhash[(vrf_id & sctppcbinfo.hashvrfmark)];
|
||||
LIST_INSERT_HEAD(bucket, vrf, next_vrf);
|
||||
@ -186,7 +177,7 @@ sctp_allocate_vrf(int vrf_id)
|
||||
|
||||
|
||||
struct sctp_ifn *
|
||||
sctp_find_ifn(struct sctp_vrf *vrf, void *ifn, uint32_t ifn_index)
|
||||
sctp_find_ifn(void *ifn, uint32_t ifn_index)
|
||||
{
|
||||
struct sctp_ifn *sctp_ifnp;
|
||||
struct sctp_ifnlist *hash_ifn_head;
|
||||
@ -195,7 +186,7 @@ sctp_find_ifn(struct sctp_vrf *vrf, void *ifn, uint32_t ifn_index)
|
||||
* We assume the lock is held for the addresses if thats wrong
|
||||
* problems could occur :-)
|
||||
*/
|
||||
hash_ifn_head = &vrf->vrf_ifn_hash[(ifn_index & vrf->vrf_ifn_hashmark)];
|
||||
hash_ifn_head = &sctppcbinfo.vrf_ifn_hash[(ifn_index & sctppcbinfo.vrf_ifn_hashmark)];
|
||||
LIST_FOREACH(sctp_ifnp, hash_ifn_head, next_bucket) {
|
||||
if (sctp_ifnp->ifn_index == ifn_index) {
|
||||
return (sctp_ifnp);
|
||||
@ -239,15 +230,11 @@ sctp_free_ifn(struct sctp_ifn *sctp_ifnp)
|
||||
}
|
||||
|
||||
void
|
||||
sctp_update_ifn_mtu(uint32_t vrf_id, uint32_t ifn_index, uint32_t mtu)
|
||||
sctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu)
|
||||
{
|
||||
struct sctp_ifn *sctp_ifnp;
|
||||
struct sctp_vrf *vrf;
|
||||
|
||||
vrf = sctp_find_vrf(vrf_id);
|
||||
if (vrf == NULL)
|
||||
return;
|
||||
sctp_ifnp = sctp_find_ifn(vrf, (void *)NULL, ifn_index);
|
||||
sctp_ifnp = sctp_find_ifn((void *)NULL, ifn_index);
|
||||
if (sctp_ifnp != NULL) {
|
||||
sctp_ifnp->ifn_mtu = mtu;
|
||||
}
|
||||
@ -272,7 +259,7 @@ sctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock)
|
||||
{
|
||||
struct sctp_ifn *found;
|
||||
|
||||
found = sctp_find_ifn(sctp_ifnp->vrf, sctp_ifnp->ifn_p, sctp_ifnp->ifn_index);
|
||||
found = sctp_find_ifn(sctp_ifnp->ifn_p, sctp_ifnp->ifn_index);
|
||||
if (found == NULL) {
|
||||
/* Not in the list.. sorry */
|
||||
return;
|
||||
@ -314,7 +301,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
sctp_ifnp = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
sctp_ifnp = sctp_find_ifn(ifn, ifn_index);
|
||||
if (sctp_ifnp == NULL) {
|
||||
/*
|
||||
* build one and add it, can't hold lock until after malloc
|
||||
@ -340,7 +327,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
|
||||
} else {
|
||||
memcpy(sctp_ifnp->ifn_name, "unknown", min(7, SCTP_IFNAMSIZ));
|
||||
}
|
||||
hash_ifn_head = &vrf->vrf_ifn_hash[(ifn_index & vrf->vrf_ifn_hashmark)];
|
||||
hash_ifn_head = &sctppcbinfo.vrf_ifn_hash[(ifn_index & sctppcbinfo.vrf_ifn_hashmark)];
|
||||
LIST_INIT(&sctp_ifnp->ifalist);
|
||||
SCTP_IPI_ADDR_LOCK();
|
||||
LIST_INSERT_HEAD(hash_ifn_head, sctp_ifnp, next_bucket);
|
||||
@ -1741,7 +1728,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int iphlen, int offset,
|
||||
* port with all addresses bound.
|
||||
*/
|
||||
int
|
||||
sctp_inpcb_alloc(struct socket *so)
|
||||
sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
{
|
||||
/*
|
||||
* we get called when a new endpoint starts up. We need to allocate
|
||||
@ -1828,7 +1815,7 @@ sctp_inpcb_alloc(struct socket *so)
|
||||
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
inp->def_vrf_id = SCTP_DEFAULT_VRFID;
|
||||
inp->def_vrf_id = vrf_id;
|
||||
|
||||
SCTP_INP_INFO_WLOCK();
|
||||
SCTP_INP_LOCK_INIT(inp);
|
||||
@ -4588,6 +4575,9 @@ sctp_pcb_init()
|
||||
sctppcbinfo.sctp_vrfhash = SCTP_HASH_INIT(SCTP_SIZE_OF_VRF_HASH,
|
||||
&sctppcbinfo.hashvrfmark);
|
||||
|
||||
sctppcbinfo.vrf_ifn_hash = SCTP_HASH_INIT(SCTP_VRF_IFN_HASH_SIZE,
|
||||
&sctppcbinfo.vrf_ifn_hashmark);
|
||||
|
||||
/* init the zones */
|
||||
/*
|
||||
* FIX ME: Should check for NULL returns, but if it does fail we are
|
||||
|
@ -59,12 +59,12 @@ TAILQ_HEAD(sctp_streamhead, sctp_stream_queue_pending);
|
||||
struct sctp_vrf {
|
||||
LIST_ENTRY(sctp_vrf) next_vrf;
|
||||
struct sctp_ifalist *vrf_addr_hash;
|
||||
struct sctp_ifnlist *vrf_ifn_hash;
|
||||
struct sctp_ifnlist ifnlist;
|
||||
uint32_t vrf_id;
|
||||
uint32_t tbl_id_v4; /* default v4 table id */
|
||||
uint32_t tbl_id_v6; /* default v6 table id */
|
||||
uint32_t total_ifa_count;
|
||||
u_long vrf_addr_hashmark;
|
||||
u_long vrf_ifn_hashmark;
|
||||
};
|
||||
|
||||
struct sctp_ifn {
|
||||
@ -166,6 +166,9 @@ struct sctp_epinfo {
|
||||
struct sctp_vrflist *sctp_vrfhash;
|
||||
u_long hashvrfmark;
|
||||
|
||||
struct sctp_ifnlist *vrf_ifn_hash;
|
||||
u_long vrf_ifn_hashmark;
|
||||
|
||||
struct sctppcbhead listhead;
|
||||
struct sctpladdr addr_wq;
|
||||
|
||||
@ -416,7 +419,7 @@ int SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b);
|
||||
void sctp_fill_pcbinfo(struct sctp_pcbinfo *);
|
||||
|
||||
struct sctp_ifn *
|
||||
sctp_find_ifn(struct sctp_vrf *vrf, void *ifn, uint32_t ifn_index);
|
||||
sctp_find_ifn(void *ifn, uint32_t ifn_index);
|
||||
|
||||
struct sctp_vrf *sctp_allocate_vrf(int vrfid);
|
||||
|
||||
@ -426,9 +429,10 @@ struct sctp_ifa *
|
||||
sctp_add_addr_to_vrf(uint32_t vrfid,
|
||||
void *ifn, uint32_t ifn_index, uint32_t ifn_type,
|
||||
const char *if_name,
|
||||
void *ifa, struct sockaddr *addr, uint32_t ifa_flags, int dynamic_add);
|
||||
void *ifa, struct sockaddr *addr, uint32_t ifa_flags,
|
||||
int dynamic_add);
|
||||
|
||||
void sctp_update_ifn_mtu(uint32_t vrf_id, uint32_t ifn_index, uint32_t mtu);
|
||||
void sctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu);
|
||||
|
||||
void sctp_free_ifn(struct sctp_ifn *sctp_ifnp);
|
||||
void sctp_free_ifa(struct sctp_ifa *sctp_ifap);
|
||||
@ -479,7 +483,7 @@ struct sctp_tcb *
|
||||
sctp_findassociation_ep_asconf(struct mbuf *, int, int,
|
||||
struct sctphdr *, struct sctp_inpcb **, struct sctp_nets **);
|
||||
|
||||
int sctp_inpcb_alloc(struct socket *);
|
||||
int sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id);
|
||||
|
||||
int sctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id);
|
||||
|
||||
|
@ -383,7 +383,6 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
|
||||
int error;
|
||||
uint32_t vrf_id;
|
||||
|
||||
|
||||
/* FIX, for non-bsd is this right? */
|
||||
vrf_id = SCTP_DEFAULT_VRFID;
|
||||
|
||||
@ -487,6 +486,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
|
||||
struct sctp_inpcb *inp;
|
||||
struct inpcb *ip_inp;
|
||||
int error;
|
||||
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
|
||||
|
||||
#ifdef IPSEC
|
||||
uint32_t flags;
|
||||
@ -500,7 +500,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
error = sctp_inpcb_alloc(so);
|
||||
error = sctp_inpcb_alloc(so, vrf_id);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
@ -543,6 +543,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
|
||||
struct in6pcb *inp6;
|
||||
int error;
|
||||
struct sctp_inpcb *inp;
|
||||
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
|
||||
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
if (inp != NULL)
|
||||
@ -553,10 +554,11 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
error = sctp_inpcb_alloc(so);
|
||||
error = sctp_inpcb_alloc(so, vrf_id);
|
||||
if (error)
|
||||
return error;
|
||||
inp = (struct sctp_inpcb *)so->so_pcb;
|
||||
SCTP_INP_WLOCK(inp);
|
||||
inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
|
||||
inp6 = (struct in6pcb *)inp;
|
||||
|
||||
@ -575,6 +577,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
|
||||
* Hmm what about the IPSEC stuff that is missing here but in
|
||||
* sctp_attach()?
|
||||
*/
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user