* add an asconf operation for the given ifa and type. * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR. * returns 0 if completed, -1 if not completed, 1 if immediate send is * advisable. */
| 1338 | * advisable. |
| 1339 | */ |
| 1340 | static int |
| 1341 | sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, |
| 1342 | uint16_t type) |
| 1343 | { |
| 1344 | uint32_t status; |
| 1345 | int pending_delete_queued = 0; |
| 1346 | int last; |
| 1347 | |
| 1348 | /* see if peer supports ASCONF */ |
| 1349 | if (stcb->asoc.asconf_supported == 0) { |
| 1350 | return (-1); |
| 1351 | } |
| 1352 | |
| 1353 | /* |
| 1354 | * if this is deleting the last address from the assoc, mark it as |
| 1355 | * pending. |
| 1356 | */ |
| 1357 | if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending) { |
| 1358 | if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { |
| 1359 | last = (sctp_local_addr_count(stcb) == 0); |
| 1360 | } else { |
| 1361 | last = (sctp_local_addr_count(stcb) == 1); |
| 1362 | } |
| 1363 | if (last) { |
| 1364 | /* set the pending delete info only */ |
| 1365 | stcb->asoc.asconf_del_pending = 1; |
| 1366 | stcb->asoc.asconf_addr_del_pending = ifa; |
| 1367 | atomic_add_int(&ifa->refcount, 1); |
| 1368 | SCTPDBG(SCTP_DEBUG_ASCONF2, |
| 1369 | "asconf_queue_add: mark delete last address pending\n"); |
| 1370 | return (-1); |
| 1371 | } |
| 1372 | } |
| 1373 | |
| 1374 | /* queue an asconf parameter */ |
| 1375 | status = sctp_asconf_queue_mgmt(stcb, ifa, type); |
| 1376 | |
| 1377 | /* |
| 1378 | * if this is an add, and there is a delete also pending (i.e. the |
| 1379 | * last local address is being changed), queue the pending delete |
| 1380 | * too. |
| 1381 | */ |
| 1382 | if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) { |
| 1383 | /* queue in the pending delete */ |
| 1384 | if (sctp_asconf_queue_mgmt(stcb, |
| 1385 | stcb->asoc.asconf_addr_del_pending, |
| 1386 | SCTP_DEL_IP_ADDRESS) == 0) { |
| 1387 | SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queuing pending delete\n"); |
| 1388 | pending_delete_queued = 1; |
| 1389 | /* clear out the pending delete info */ |
| 1390 | stcb->asoc.asconf_del_pending = 0; |
| 1391 | sctp_free_ifa(stcb->asoc.asconf_addr_del_pending); |
| 1392 | stcb->asoc.asconf_addr_del_pending = NULL; |
| 1393 | } |
| 1394 | } |
| 1395 | |
| 1396 | if (pending_delete_queued) { |
| 1397 | struct sctp_nets *net; |
no test coverage detected