- * add an asconf delete IP address parameter to the queue by sockaddr and * possibly with no sctp_ifa available. This is only called by the routine * that checks the addresses in an INIT-ACK against the current address list. * returns 0 if completed, non-zero if not completed. * NOTE: if an add is already scheduled (and not yet sent out), simply * remove it from queue. If a duplicate oper
| 1436 | * new one. |
| 1437 | */ |
| 1438 | static int |
| 1439 | sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) |
| 1440 | { |
| 1441 | struct sctp_ifa *ifa; |
| 1442 | struct sctp_asconf_addr *aa, *aa_next; |
| 1443 | |
| 1444 | if (stcb == NULL) { |
| 1445 | return (-1); |
| 1446 | } |
| 1447 | /* see if peer supports ASCONF */ |
| 1448 | if (stcb->asoc.asconf_supported == 0) { |
| 1449 | return (-1); |
| 1450 | } |
| 1451 | /* make sure the request isn't already in the queue */ |
| 1452 | TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { |
| 1453 | /* address match? */ |
| 1454 | if (sctp_asconf_addr_match(aa, sa) == 0) |
| 1455 | continue; |
| 1456 | /* is the request already in queue (sent or not) */ |
| 1457 | if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) { |
| 1458 | return (-1); |
| 1459 | } |
| 1460 | /* is the negative request already in queue, and not sent */ |
| 1461 | if (aa->sent == 1) |
| 1462 | continue; |
| 1463 | if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) { |
| 1464 | /* add already queued, so remove existing entry */ |
| 1465 | TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); |
| 1466 | sctp_del_local_addr_restricted(stcb, aa->ifa); |
| 1467 | /* free the entry */ |
| 1468 | SCTP_FREE(aa, SCTP_M_ASC_ADDR); |
| 1469 | return (-1); |
| 1470 | } |
| 1471 | } /* for each aa */ |
| 1472 | |
| 1473 | /* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */ |
| 1474 | ifa = sctp_find_ifa_by_addr(sa, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED); |
| 1475 | |
| 1476 | /* adding new request to the queue */ |
| 1477 | SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), |
| 1478 | SCTP_M_ASC_ADDR); |
| 1479 | if (aa == NULL) { |
| 1480 | /* didn't get memory */ |
| 1481 | SCTPDBG(SCTP_DEBUG_ASCONF1, |
| 1482 | "sctp_asconf_queue_sa_delete: failed to get memory!\n"); |
| 1483 | return (-1); |
| 1484 | } |
| 1485 | aa->special_del = 0; |
| 1486 | /* fill in asconf address parameter fields */ |
| 1487 | /* top level elements are "networked" during send */ |
| 1488 | aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS; |
| 1489 | aa->ifa = ifa; |
| 1490 | if (ifa) |
| 1491 | atomic_add_int(&ifa->refcount, 1); |
| 1492 | /* correlation_id filled in during send routine later... */ |
| 1493 | switch (sa->sa_family) { |
| 1494 | #ifdef INET6 |
| 1495 | case AF_INET6: |
no test coverage detected