Skip to content

Commit

Permalink
Improve handling of address changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tuexen committed Nov 3, 2024
1 parent ead08b7 commit b28f0b5
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 138 deletions.
7 changes: 3 additions & 4 deletions usrsctplib/netinet/sctp_bsd_addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,12 +713,11 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
(void *)ifa, ifa->ifa_addr, ifa_flags, 1);
} else {
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
(void *)ifa->ifa_ifp,
#if defined(__APPLE__) && !defined(__Userspace__)
ifnet_index(ifa->ifa_ifp),
ifnet_name(ifa->ifa_ifp));
ifnet_index(ifa->ifa_ifp));
#else
ifa->ifa_ifp->if_index,
ifa->ifa_ifp->if_xname);
ifa->ifa_ifp->if_index);
#endif

/* We don't bump refcount here so when it completes
Expand Down
135 changes: 18 additions & 117 deletions usrsctplib/netinet/sctp_pcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,13 @@ sctp_find_ifn(void *ifn, uint32_t ifn_index)
struct sctp_ifnlist *hash_ifn_head;

SCTP_IPI_ADDR_LOCK_ASSERT();
#if defined(__FreeBSD__) && !defined(__Userspace__)
KASSERT(ifn != NULL, ("sctp_find_ifn(NULL, %u) called", ifn_index));
#endif
hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))];
LIST_FOREACH(sctp_ifnp, hash_ifn_head, next_bucket) {
if (sctp_ifnp->ifn_index == ifn_index) {
break;
}
if (ifn != NULL && sctp_ifnp->ifn_p == ifn) {
if (sctp_ifnp->ifn_index == ifn_index &&
sctp_ifnp->ifn_p == ifn) {
break;
}
}
Expand Down Expand Up @@ -335,90 +336,6 @@ sctp_delete_ifn(struct sctp_ifn *sctp_ifnp)
sctp_free_ifn(sctp_ifnp);
}

void
sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr,
const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap;

SCTP_IPI_ADDR_RLOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id);
goto out;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n");
goto out;
}
if (sctp_ifap->ifn_p == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unusable\n");
goto out;
}
if (if_name) {
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n",
sctp_ifap->ifn_p->ifn_name, if_name);
goto out;
}
} else {
if (sctp_ifap->ifn_p->ifn_index != ifn_index) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n",
sctp_ifap->ifn_p->ifn_index, ifn_index);
goto out;
}
}

sctp_ifap->localifa_flags &= (~SCTP_ADDR_VALID);
sctp_ifap->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
out:
SCTP_IPI_ADDR_RUNLOCK();
}

void
sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr,
const char *if_name, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap;

SCTP_IPI_ADDR_RLOCK();
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id);
goto out;
}
sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED);
if (sctp_ifap == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n");
goto out;
}
if (sctp_ifap->ifn_p == NULL) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unusable\n");
goto out;
}
if (if_name) {
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n",
sctp_ifap->ifn_p->ifn_name, if_name);
goto out;
}
} else {
if (sctp_ifap->ifn_p->ifn_index != ifn_index) {
SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n",
sctp_ifap->ifn_p->ifn_index, ifn_index);
goto out;
}
}

sctp_ifap->localifa_flags &= (~SCTP_ADDR_IFA_UNUSEABLE);
sctp_ifap->localifa_flags |= SCTP_ADDR_VALID;
out:
SCTP_IPI_ADDR_RUNLOCK();
}

/*-
* Add an ifa to an ifn.
* Register the interface as necessary.
Expand Down Expand Up @@ -504,9 +421,9 @@ sctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap)

struct sctp_ifa *
sctp_add_addr_to_vrf(uint32_t vrf_id, 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)
uint32_t ifn_type, const char *if_name, void *ifa,
struct sockaddr *addr, uint32_t ifa_flags,
int dynamic_add)
{
struct sctp_vrf *vrf;
struct sctp_ifn *sctp_ifnp, *new_sctp_ifnp;
Expand Down Expand Up @@ -581,7 +498,8 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
if (sctp_ifap != NULL) {
/* The address being added is already or still known. */
if (sctp_ifap->ifn_p != NULL) {
if (sctp_ifap->ifn_p->ifn_index == ifn_index) {
if (sctp_ifap->ifn_p->ifn_index == ifn_index &&
sctp_ifap->ifn_p->ifn_p == ifn) {
SCTPDBG(SCTP_DEBUG_PCB4,
"Using existing ifn %s (0x%x) for ifa %p\n",
sctp_ifap->ifn_p->ifn_name, ifn_index,
Expand Down Expand Up @@ -748,8 +666,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
*/
SCTPDBG(SCTP_DEBUG_PCB4, "Lost an address change?\n");
/* Opps, must decrement the count */
sctp_del_addr_from_vrf(vrf_id, addr, ifn_index,
if_name);
sctp_del_addr_from_vrf(vrf_id, addr, ifn, ifn_index);
return (NULL);
}
SCTP_INCR_LADDR_COUNT();
Expand All @@ -774,7 +691,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,

void
sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
uint32_t ifn_index, const char *if_name)
void *ifn, uint32_t ifn_index)
{
struct sctp_vrf *vrf;
struct sctp_ifa *sctp_ifap;
Expand All @@ -795,28 +712,12 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
if (sctp_ifap != NULL) {
/* Validate the delete */
if (sctp_ifap->ifn_p) {
bool valid = false;
/*-
* The name has priority over the ifn_index
* if its given.
*/
if (if_name) {
if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) == 0) {
/* They match its a correct delete */
valid = true;
}
}
if (!valid) {
/* last ditch check ifn_index */
if (ifn_index == sctp_ifap->ifn_p->ifn_index) {
valid = true;
}
}
if (!valid) {
SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s does not match addresses\n",
ifn_index, ((if_name == NULL) ? "NULL" : if_name));
SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s - ignoring delete\n",
sctp_ifap->ifn_p->ifn_index, sctp_ifap->ifn_p->ifn_name);
if (ifn_index != sctp_ifap->ifn_p->ifn_index ||
ifn != sctp_ifap->ifn_p->ifn_p) {
SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d (%p) ifname:%s - ignoring delete\n",
sctp_ifap->ifn_p->ifn_index,
sctp_ifap->ifn_p->ifn_p,
sctp_ifap->ifn_p->ifn_name);
SCTP_IPI_ADDR_WUNLOCK();
return;
}
Expand Down
14 changes: 1 addition & 13 deletions usrsctplib/netinet/sctp_pcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -681,18 +681,6 @@ struct sctp_vrf *sctp_allocate_vrf(int vrfid);
struct sctp_vrf *sctp_find_vrf(uint32_t vrfid);
void sctp_free_vrf(struct sctp_vrf *vrf);

/*-
* Change address state, can be used if
* O/S supports telling transports about
* changes to IFA/IFN's (link layer triggers).
* If a ifn goes down, we will do src-addr-selection
* and NOT use that, as a source address. This does
* not stop the routing system from routing out
* that interface, but we won't put it as a source.
*/
void sctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index);
void sctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, const char *if_name, uint32_t ifn_index);

struct sctp_ifa *
sctp_add_addr_to_vrf(uint32_t vrfid,
void *ifn, uint32_t ifn_index, uint32_t ifn_type,
Expand All @@ -703,7 +691,7 @@ sctp_add_addr_to_vrf(uint32_t vrfid,
void sctp_free_ifa(struct sctp_ifa *sctp_ifap);

void sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
uint32_t ifn_index, const char *if_name);
void *ifn, uint32_t ifn_index);

struct sctp_nets *sctp_findnet(struct sctp_tcb *, struct sockaddr *);

Expand Down
3 changes: 1 addition & 2 deletions usrsctplib/user_recv_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ sctp_handle_ifamsg(unsigned char type, unsigned short index, struct sockaddr *sa
1);
} else {
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
if_nametoindex(ifa->ifa_name),
ifa->ifa_name);
NULL, if_nametoindex(ifa->ifa_name));
}
freeifaddrs(ifas);
}
Expand Down
3 changes: 1 addition & 2 deletions usrsctplib/user_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -3154,8 +3154,7 @@ usrsctp_deregister_address(void *addr)
sconn.sconn_addr = addr;
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID,
(struct sockaddr *)&sconn,
0xffffffff,
"conn");
NULL, 0xffffffff);
}

#define PREAMBLE_FORMAT "\n%c %02d:%02d:%02d.%06ld "
Expand Down

0 comments on commit b28f0b5

Please sign in to comment.