Deleted Added
sdiff udiff text old ( 166675 ) new ( 167598 )
full compact
1/*-
2 * Copyright (c) 2001-2007, Cisco Systems, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * a) Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.

--- 17 unchanged lines hidden (view full) ---

26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/* $KAME: sctp_pcb.c,v 1.38 2005/03/06 16:04:18 itojun Exp $ */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 166675 2007-02-12 23:24:31Z rrs $");
35
36#include <netinet/sctp_os.h>
37#include <sys/proc.h>
38#include <netinet/sctp_var.h>
39#include <netinet/sctp_pcb.h>
40#include <netinet/sctputil.h>
41#include <netinet/sctp.h>
42#include <netinet/sctp_header.h>
43#include <netinet/sctp_asconf.h>
44#include <netinet/sctp_output.h>
45#include <netinet/sctp_timer.h>
46
47
48#ifdef SCTP_DEBUG
49uint32_t sctp_debug_on = 0;
50
51#endif /* SCTP_DEBUG */
52
53
54extern int sctp_pcbtblsize;
55extern int sctp_hashtblsize;
56extern int sctp_chunkscale;
57
58struct sctp_epinfo sctppcbinfo;
59
60/* FIX: we don't handle multiple link local scopes */
61/* "scopeless" replacement IN6_ARE_ADDR_EQUAL */
62int
63SCTP6_ARE_ADDR_EQUAL(struct in6_addr *a, struct in6_addr *b)
64{
65 struct in6_addr tmp_a, tmp_b;
66
67 /* use a copy of a and b */
68 tmp_a = *a;
69 tmp_b = *b;
70 in6_clearscope(&tmp_a);
71 in6_clearscope(&tmp_b);
72 return (IN6_ARE_ADDR_EQUAL(&tmp_a, &tmp_b));
73}
74
75
76void
77sctp_fill_pcbinfo(struct sctp_pcbinfo *spcb)
78{
79 /*
80 * We really don't need to lock this, but I will just because it
81 * does not hurt.
82 */
83 SCTP_INP_INFO_RLOCK();

--- 4 unchanged lines hidden (view full) ---

88 spcb->chk_count = sctppcbinfo.ipi_count_chunk;
89 spcb->readq_count = sctppcbinfo.ipi_count_readq;
90 spcb->stream_oque = sctppcbinfo.ipi_count_strmoq;
91 spcb->free_chunks = sctppcbinfo.ipi_free_chunks;
92
93 SCTP_INP_INFO_RUNLOCK();
94}
95
96
97/*
98 * Notes on locks for FreeBSD 5 and up. All association lookups that have a
99 * definte ep, the INP structure is assumed to be locked for reading. If we
100 * need to go find the INP (ususally when a **inp is passed) then we must
101 * lock the INFO structure first and if needed lock the INP too. Note that if
102 * we lock it we must
103 *
104 */

--- 67 unchanged lines hidden (view full) ---

172 if (laddr->ifa == NULL) {
173#ifdef SCTP_DEBUG
174 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
175 printf("An ounce of prevention is worth a pound of cure\n");
176 }
177#endif
178 continue;
179 }
180 if (laddr->ifa->ifa_addr == NULL) {
181#ifdef SCTP_DEBUG
182 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
183 printf("ifa with a NULL address\n");
184 }
185#endif
186 continue;
187 }
188 if (laddr->ifa->ifa_addr->sa_family ==
189 to->sa_family) {
190 /* see if it matches */
191 struct sockaddr_in *intf_addr, *sin;
192
193 intf_addr = (struct sockaddr_in *)
194 laddr->ifa->ifa_addr;
195 sin = (struct sockaddr_in *)to;
196 if (from->sa_family == AF_INET) {
197 if (sin->sin_addr.s_addr ==
198 intf_addr->sin_addr.s_addr) {
199 match = 1;
200 break;
201 }
202 } else {
203 struct sockaddr_in6 *intf_addr6;
204 struct sockaddr_in6 *sin6;
205
206 sin6 = (struct sockaddr_in6 *)
207 to;
208 intf_addr6 = (struct sockaddr_in6 *)
209 laddr->ifa->ifa_addr;
210
211 if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
212 &intf_addr6->sin6_addr)) {
213 match = 1;
214 break;
215 }
216 }
217 }

--- 372 unchanged lines hidden (view full) ---

590 }
591 SCTP_INP_INFO_RUNLOCK();
592 return (NULL);
593}
594
595
596static struct sctp_inpcb *
597sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
598 uint16_t lport)
599{
600 struct sctp_inpcb *inp;
601 struct sockaddr_in *sin;
602 struct sockaddr_in6 *sin6;
603 struct sctp_laddr *laddr;
604
605 /*
606 * Endpoing probe expects that the INP_INFO is locked.
607 */
608 if (nam->sa_family == AF_INET) {
609 sin = (struct sockaddr_in *)nam;
610 sin6 = NULL;
611 } else if (nam->sa_family == AF_INET6) {

--- 22 unchanged lines hidden (view full) ---

634 continue;
635 }
636 /* A V6 address and the endpoint is NOT bound V6 */
637 if (nam->sa_family == AF_INET6 &&
638 (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
639 SCTP_INP_RUNLOCK(inp);
640 continue;
641 }
642 SCTP_INP_RUNLOCK(inp);
643 return (inp);
644 }
645 SCTP_INP_RUNLOCK(inp);
646 }
647
648 if ((nam->sa_family == AF_INET) &&
649 (sin->sin_addr.s_addr == INADDR_ANY)) {
650 /* Can't hunt for one that has no address specified */

--- 20 unchanged lines hidden (view full) ---

671 /*
672 * Ok this could be a likely candidate, look at all of its
673 * addresses
674 */
675 if (inp->sctp_lport != lport) {
676 SCTP_INP_RUNLOCK(inp);
677 continue;
678 }
679 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
680 if (laddr->ifa == NULL) {
681#ifdef SCTP_DEBUG
682 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
683 printf("An ounce of prevention is worth a pound of cure\n");
684 }
685#endif
686 continue;
687 }
688#ifdef SCTP_DEBUG
689 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
690 printf("Ok laddr->ifa:%p is possible, ",
691 laddr->ifa);
692 }
693#endif
694 if (laddr->ifa->ifa_addr == NULL) {
695#ifdef SCTP_DEBUG
696 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
697 printf("Huh IFA as an ifa_addr=NULL, ");
698 }
699#endif
700 continue;
701 }
702 if (laddr->ifa->ifa_addr->sa_family == nam->sa_family) {
703 /* possible, see if it matches */
704 struct sockaddr_in *intf_addr;
705
706 intf_addr = (struct sockaddr_in *)
707 laddr->ifa->ifa_addr;
708 if (nam->sa_family == AF_INET) {
709 if (sin->sin_addr.s_addr ==
710 intf_addr->sin_addr.s_addr) {
711 SCTP_INP_RUNLOCK(inp);
712 return (inp);
713 }
714 } else if (nam->sa_family == AF_INET6) {
715 struct sockaddr_in6 *intf_addr6;
716
717 intf_addr6 = (struct sockaddr_in6 *)
718 laddr->ifa->ifa_addr;
719 if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
720 &intf_addr6->sin6_addr)) {
721 SCTP_INP_RUNLOCK(inp);
722 return (inp);
723 }
724 }
725 }
726 }
727 SCTP_INP_RUNLOCK(inp);
728 }
729 return (NULL);
730}
731
732
733struct sctp_inpcb *
734sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock)
735{
736 /*
737 * First we check the hash table to see if someone has this port
738 * bound with just the port.
739 */
740 struct sctp_inpcb *inp;
741 struct sctppcbhead *head;
742 struct sockaddr_in *sin;

--- 17 unchanged lines hidden (view full) ---

760 */
761 /* Find the head of the ALLADDR chain */
762 if (have_lock == 0) {
763 SCTP_INP_INFO_RLOCK();
764
765 }
766 head = &sctppcbinfo.sctp_ephash[SCTP_PCBHASH_ALLADDR(lport,
767 sctppcbinfo.hashmark)];
768 inp = sctp_endpoint_probe(nam, head, lport);
769
770 /*
771 * If the TCP model exists it could be that the main listening
772 * endpoint is gone but there exists a connected socket for this guy
773 * yet. If so we can return the first one that we find. This may NOT
774 * be the correct one but the sctp_findassociation_ep_addr has
775 * further code to look at all TCP models.
776 */

--- 4 unchanged lines hidden (view full) ---

781 /*
782 * This is real gross, but we do NOT have a remote
783 * port at this point depending on who is calling.
784 * We must therefore look for ANY one that matches
785 * our local port :/
786 */
787 head = &sctppcbinfo.sctp_tcpephash[i];
788 if (LIST_FIRST(head)) {
789 inp = sctp_endpoint_probe(nam, head, lport);
790 if (inp) {
791 /* Found one */
792 break;
793 }
794 }
795 }
796 }
797 if (inp) {

--- 7 unchanged lines hidden (view full) ---

805
806/*
807 * Find an association for an endpoint with the pointer to whom you want to
808 * send to and the endpoint pointer. The address can be IPv4 or IPv6. We may
809 * need to change the *to to some other struct like a mbuf...
810 */
811struct sctp_tcb *
812sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
813 struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool)
814{
815 struct sctp_inpcb *inp;
816 struct sctp_tcb *retval;
817
818 SCTP_INP_INFO_RLOCK();
819 if (find_tcp_pool) {
820 if (inp_p != NULL) {
821 retval = sctp_tcb_special_locate(inp_p, from, to, netp);
822 } else {
823 retval = sctp_tcb_special_locate(&inp, from, to, netp);
824 }
825 if (retval != NULL) {
826 SCTP_INP_INFO_RUNLOCK();
827 return (retval);
828 }
829 }
830 inp = sctp_pcb_findep(to, 0, 1);
831 if (inp_p != NULL) {
832 *inp_p = inp;
833 }
834 SCTP_INP_INFO_RUNLOCK();
835
836 if (inp == NULL) {
837 return (NULL);
838 }

--- 183 unchanged lines hidden (view full) ---

1022{
1023 int find_tcp_pool;
1024 struct ip *iph;
1025 struct sctp_tcb *retval;
1026 struct sockaddr_storage to_store, from_store;
1027 struct sockaddr *to = (struct sockaddr *)&to_store;
1028 struct sockaddr *from = (struct sockaddr *)&from_store;
1029 struct sctp_inpcb *inp;
1030
1031
1032 iph = mtod(m, struct ip *);
1033 if (iph->ip_v == IPVERSION) {
1034 /* its IPv4 */
1035 struct sockaddr_in *from4;
1036
1037 from4 = (struct sockaddr_in *)&from_store;
1038 bzero(from4, sizeof(*from4));
1039 from4->sin_family = AF_INET;

--- 66 unchanged lines hidden (view full) ---

1106 (ch->chunk_type != SCTP_INITIATION_ACK) &&
1107 (ch->chunk_type != SCTP_COOKIE_ACK) &&
1108 (ch->chunk_type != SCTP_COOKIE_ECHO)) {
1109 /* Other chunk types go to the tcp pool. */
1110 find_tcp_pool = 1;
1111 }
1112 if (inp_p) {
1113 retval = sctp_findassociation_addr_sa(to, from, inp_p, netp,
1114 find_tcp_pool);
1115 inp = *inp_p;
1116 } else {
1117 retval = sctp_findassociation_addr_sa(to, from, &inp, netp,
1118 find_tcp_pool);
1119 }
1120#ifdef SCTP_DEBUG
1121 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
1122 printf("retval:%p inp:%p\n", retval, inp);
1123 }
1124#endif
1125 if (retval == NULL && inp) {
1126 /* Found a EP but not this address */

--- 150 unchanged lines hidden (view full) ---

1277 stcb = sctp_findassociation_ep_addr(inp_p,
1278 (struct sockaddr *)&remote_store, netp,
1279 (struct sockaddr *)&local_store, NULL);
1280 }
1281 return (stcb);
1282}
1283
1284
1285extern int sctp_max_burst_default;
1286
1287extern unsigned int sctp_delayed_sack_time_default;
1288extern unsigned int sctp_heartbeat_interval_default;
1289extern unsigned int sctp_pmtu_raise_time_default;
1290extern unsigned int sctp_shutdown_guard_time_default;
1291extern unsigned int sctp_secret_lifetime_default;
1292
1293extern unsigned int sctp_rto_max_default;
1294extern unsigned int sctp_rto_min_default;
1295extern unsigned int sctp_rto_initial_default;
1296extern unsigned int sctp_init_rto_max_default;
1297extern unsigned int sctp_valid_cookie_life_default;
1298extern unsigned int sctp_init_rtx_max_default;
1299extern unsigned int sctp_assoc_rtx_max_default;
1300extern unsigned int sctp_path_rtx_max_default;
1301extern unsigned int sctp_nr_outgoing_streams_default;
1302
1303/*
1304 * allocate a sctp_inpcb and setup a temporary binding to a port/all
1305 * addresses. This way if we don't get a bind we by default pick a ephemeral
1306 * port with all addresses bound.
1307 */
1308int
1309sctp_inpcb_alloc(struct socket *so)
1310{

--- 48 unchanged lines hidden (view full) ---

1359 }
1360#endif /* IPSEC */
1361 SCTP_INCR_EP_COUNT();
1362 inp->ip_inp.inp.inp_ip_ttl = ip_defttl;
1363 SCTP_INP_INFO_WUNLOCK();
1364
1365 so->so_pcb = (caddr_t)inp;
1366
1367 if ((so->so_type == SOCK_DGRAM) ||
1368 (so->so_type == SOCK_SEQPACKET)) {
1369 /* UDP style socket */
1370 inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
1371 SCTP_PCB_FLAGS_UNBOUND);
1372 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
1373 /* Be sure it is NON-BLOCKING IO for UDP */
1374 /* so->so_state |= SS_NBIO; */
1375 } else if (so->so_type == SOCK_STREAM) {
1376 /* TCP style socket */
1377 inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
1378 SCTP_PCB_FLAGS_UNBOUND);
1379 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
1380 /* Be sure we have blocking IO by default */
1381 so->so_state &= ~SS_NBIO;
1382 } else {
1383 /*
1384 * unsupported socket type (RAW, etc)- in case we missed it
1385 * in protosw
1386 */
1387 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
1388 return (EOPNOTSUPP);
1389 }
1390 inp->sctp_tcbhash = SCTP_HASH_INIT(sctp_pcbtblsize,
1391 &inp->sctp_hashmark);
1392 if (inp->sctp_tcbhash == NULL) {
1393 printf("Out of SCTP-INPCB->hashinit - no resources\n");
1394 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
1395 return (ENOBUFS);
1396 }
1397 SCTP_INP_INFO_WLOCK();
1398 SCTP_INP_LOCK_INIT(inp);
1399 SCTP_INP_READ_INIT(inp);
1400 SCTP_ASOC_CREATE_LOCK_INIT(inp);
1401 /* lock the new ep */
1402 SCTP_INP_WLOCK(inp);
1403
1404 /* add it to the info area */
1405 LIST_INSERT_HEAD(&sctppcbinfo.listhead, inp, sctp_list);
1406 SCTP_INP_INFO_WUNLOCK();
1407
1408 TAILQ_INIT(&inp->read_queue);
1409 LIST_INIT(&inp->sctp_addr_list);
1410 LIST_INIT(&inp->sctp_asoc_list);
1411
1412#ifdef SCTP_TRACK_FREED_ASOCS
1413 /* TEMP CODE */
1414 LIST_INIT(&inp->sctp_asoc_free_list);
1415#endif
1416 /* Init the timer structure for signature change */
1417 SCTP_OS_TIMER_INIT(&inp->sctp_ep.signature_change.timer);

--- 10 unchanged lines hidden (view full) ---

1428 m->sctp_timeoutticks[SCTP_TIMER_PMTU] = SEC_TO_TICKS(sctp_pmtu_raise_time_default);
1429 m->sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] = SEC_TO_TICKS(sctp_shutdown_guard_time_default);
1430 m->sctp_timeoutticks[SCTP_TIMER_SIGNATURE] = SEC_TO_TICKS(sctp_secret_lifetime_default);
1431 /* all max/min max are in ms */
1432 m->sctp_maxrto = sctp_rto_max_default;
1433 m->sctp_minrto = sctp_rto_min_default;
1434 m->initial_rto = sctp_rto_initial_default;
1435 m->initial_init_rto_max = sctp_init_rto_max_default;
1436
1437 m->max_open_streams_intome = MAX_SCTP_STREAMS;
1438
1439 m->max_init_times = sctp_init_rtx_max_default;
1440 m->max_send_times = sctp_assoc_rtx_max_default;
1441 m->def_net_failure = sctp_path_rtx_max_default;
1442 m->sctp_sws_sender = SCTP_SWS_SENDER_DEF;
1443 m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF;

--- 21 unchanged lines hidden (view full) ---

1465
1466 for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
1467 m->secret_key[0][i] = sctp_select_initial_TSN(m);
1468 }
1469 sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL);
1470
1471 /* How long is a cookie good for ? */
1472 m->def_cookie_life = sctp_valid_cookie_life_default;
1473
1474 /*
1475 * Initialize authentication parameters
1476 */
1477 m->local_hmacs = sctp_default_supported_hmaclist();
1478 m->local_auth_chunks = sctp_alloc_chunklist();
1479 sctp_auth_set_default_chunks(m->local_auth_chunks);
1480 LIST_INIT(&m->shared_keys);
1481 /* add default NULL key as key id 0 */

--- 114 unchanged lines hidden (view full) ---

1596 net->rxt_timer.ep = (void *)new_inp;
1597 net->fr_timer.ep = (void *)new_inp;
1598 }
1599 SCTP_INP_WUNLOCK(new_inp);
1600 SCTP_INP_WUNLOCK(old_inp);
1601}
1602
1603static int
1604sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport)
1605{
1606 struct sctppcbhead *head;
1607 struct sctp_inpcb *t_inp;
1608
1609 head = &sctppcbinfo.sctp_ephash[SCTP_PCBHASH_ALLADDR(lport,
1610 sctppcbinfo.hashmark)];
1611
1612 LIST_FOREACH(t_inp, head, sctp_hash) {
1613 if (t_inp->sctp_lport != lport) {
1614 continue;
1615 }
1616 /* This one is in use. */
1617 /* check the v6/v4 binding issue */
1618 if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1619 SCTP_IPV6_V6ONLY(t_inp)) {
1620 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1621 /* collision in V6 space */
1622 return (1);
1623 } else {

--- 24 unchanged lines hidden (view full) ---

1648{
1649 /* bind a ep to a socket address */
1650 struct sctppcbhead *head;
1651 struct sctp_inpcb *inp, *inp_tmp;
1652 struct inpcb *ip_inp;
1653 int bindall;
1654 uint16_t lport;
1655 int error;
1656
1657 lport = 0;
1658 error = 0;
1659 bindall = 1;
1660 inp = (struct sctp_inpcb *)so->so_pcb;
1661 ip_inp = (struct inpcb *)so->so_pcb;
1662#ifdef SCTP_DEBUG
1663 if (sctp_debug_on & SCTP_DEBUG_PCB1) {

--- 43 unchanged lines hidden (view full) ---

1707 return (EINVAL);
1708 }
1709 /* this must be cleared for ifa_ifwithaddr() */
1710 sin6->sin6_scope_id = 0;
1711 } else {
1712 return (EAFNOSUPPORT);
1713 }
1714 }
1715 SCTP_INP_INFO_WLOCK();
1716 SCTP_INP_WLOCK(inp);
1717 /* increase our count due to the unlock we do */
1718 SCTP_INP_INCR_REF(inp);
1719 if (lport) {
1720 /*
1721 * Did the caller specify a port? if so we must see if a ep
1722 * already has this one bound.
1723 */
1724 /* got to be root to get at low ports */
1725 if (ntohs(lport) < IPPORT_RESERVED) {
1726 if (p && (error =
1727 priv_check(p,
1728 PRIV_NETINET_RESERVEDPORT)
1729 )) {
1730 SCTP_INP_DECR_REF(inp);
1731 SCTP_INP_WUNLOCK(inp);
1732 SCTP_INP_INFO_WUNLOCK();
1733 return (error);
1734 }
1735 }
1736 if (p == NULL) {
1737 SCTP_INP_DECR_REF(inp);
1738 SCTP_INP_WUNLOCK(inp);
1739 SCTP_INP_INFO_WUNLOCK();
1740 return (error);
1741 }
1742 SCTP_INP_WUNLOCK(inp);
1743 inp_tmp = sctp_pcb_findep(addr, 0, 1);
1744 if (inp_tmp != NULL) {
1745 /*
1746 * lock guy returned and lower count note that we
1747 * are not bound so inp_tmp should NEVER be inp. And
1748 * it is this inp (inp_tmp) that gets the reference
1749 * bump, so we must lower it.
1750 */
1751 SCTP_INP_DECR_REF(inp_tmp);
1752 SCTP_INP_DECR_REF(inp);
1753 /* unlock info */
1754 SCTP_INP_INFO_WUNLOCK();
1755 return (EADDRNOTAVAIL);
1756 }
1757 SCTP_INP_WLOCK(inp);
1758 if (bindall) {
1759 /* verify that no lport is not used by a singleton */
1760 if (sctp_isport_inuse(inp, lport)) {
1761 /* Sorry someone already has this one bound */
1762 SCTP_INP_DECR_REF(inp);
1763 SCTP_INP_WUNLOCK(inp);
1764 SCTP_INP_INFO_WUNLOCK();
1765 return (EADDRNOTAVAIL);
1766 }
1767 }
1768 } else {

--- 4 unchanged lines hidden (view full) ---

1773
1774 /*
1775 * setup the inp to the top (I could use the union but this
1776 * is just as easy
1777 */
1778 uint32_t port_guess;
1779 uint16_t port_attempt;
1780 int not_done = 1;
1781
1782 while (not_done) {
1783 port_guess = sctp_select_initial_TSN(&inp->sctp_ep);
1784 port_attempt = (port_guess & 0x0000ffff);
1785 if (port_attempt == 0) {
1786 goto next_half;
1787 }
1788 if (port_attempt < IPPORT_RESERVED) {
1789 port_attempt += IPPORT_RESERVED;
1790 }
1791 if (sctp_isport_inuse(inp, htons(port_attempt)) == 0) {
1792 /* got a port we can use */
1793 not_done = 0;
1794 continue;
1795 }
1796 /* try upper half */
1797 next_half:
1798 port_attempt = ((port_guess >> 16) & 0x0000ffff);
1799 if (port_attempt == 0) {
1800 goto last_try;
1801 }
1802 if (port_attempt < IPPORT_RESERVED) {
1803 port_attempt += IPPORT_RESERVED;
1804 }
1805 if (sctp_isport_inuse(inp, htons(port_attempt)) == 0) {
1806 /* got a port we can use */
1807 not_done = 0;
1808 continue;
1809 }
1810 /* try two half's added together */
1811 last_try:
1812 port_attempt = (((port_guess >> 16) & 0x0000ffff) +
1813 (port_guess & 0x0000ffff));
1814 if (port_attempt == 0) {
1815 /* get a new random number */
1816 continue;
1817 }
1818 if (port_attempt < IPPORT_RESERVED) {
1819 port_attempt += IPPORT_RESERVED;
1820 }
1821 if (sctp_isport_inuse(inp, htons(port_attempt)) == 0) {
1822 /* got a port we can use */
1823 not_done = 0;
1824 continue;
1825 }
1826 }
1827 /* we don't get out of the loop until we have a port */
1828 lport = htons(port_attempt);
1829 }
1830 SCTP_INP_DECR_REF(inp);

--- 24 unchanged lines hidden (view full) ---

1855 * address structure to the sctp_addr_list inside the ep
1856 * structure.
1857 *
1858 * We will need to allocate one and insert it at the head. The
1859 * socketopt call can just insert new addresses in there as
1860 * well. It will also have to do the embed scope kame hack
1861 * too (before adding).
1862 */
1863 struct ifaddr *ifa;
1864 struct sockaddr_storage store_sa;
1865
1866 memset(&store_sa, 0, sizeof(store_sa));
1867 if (addr->sa_family == AF_INET) {
1868 struct sockaddr_in *sin;
1869
1870 sin = (struct sockaddr_in *)&store_sa;
1871 memcpy(sin, addr, sizeof(struct sockaddr_in));

--- 5 unchanged lines hidden (view full) ---

1877 memcpy(sin6, addr, sizeof(struct sockaddr_in6));
1878 sin6->sin6_port = 0;
1879 }
1880 /*
1881 * first find the interface with the bound address need to
1882 * zero out the port to find the address! yuck! can't do
1883 * this earlier since need port for sctp_pcb_findep()
1884 */
1885 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa);
1886 if (ifa == NULL) {
1887 /* Can't find an interface with that address */
1888 SCTP_INP_WUNLOCK(inp);
1889 SCTP_INP_INFO_WUNLOCK();
1890 return (EADDRNOTAVAIL);
1891 }
1892 if (addr->sa_family == AF_INET6) {
1893 struct in6_ifaddr *ifa6;
1894
1895 ifa6 = (struct in6_ifaddr *)ifa;
1896 /*
1897 * allow binding of deprecated addresses as per RFC
1898 * 2462 and ipng discussion
1899 */
1900 if (ifa6->ia6_flags & (IN6_IFF_DETACHED |
1901 IN6_IFF_ANYCAST |
1902 IN6_IFF_NOTREADY)) {
1903 /* Can't bind a non-existent addr. */
1904 SCTP_INP_WUNLOCK(inp);
1905 SCTP_INP_INFO_WUNLOCK();
1906 return (EINVAL);
1907 }
1908 }
1909 /* we're not bound all */
1910 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL;
1911 /* set the automatic addr changes from kernel flag */
1912 if (sctp_auto_asconf == 0) {
1913 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1914 } else {
1915 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1916 }
1917 /* allow bindx() to send ASCONF's for binding changes */
1918 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF);
1919 /* add this address to the endpoint list */
1920 error = sctp_insert_laddr(&inp->sctp_addr_list, ifa);
1921 if (error != 0) {
1922 SCTP_INP_WUNLOCK(inp);
1923 SCTP_INP_INFO_WUNLOCK();
1924 return (error);
1925 }
1926 inp->laddr_count++;
1927 }
1928 /* find the bucket */

--- 30 unchanged lines hidden (view full) ---

1959 /*
1960 * Go through all iterators, we must do this since it is possible
1961 * that some iterator does NOT have the lock, but is waiting for it.
1962 * And the one that had the lock has either moved in the last
1963 * iteration or we just cleared it above. We need to find all of
1964 * those guys. The list of iterators should never be very big
1965 * though.
1966 */
1967 LIST_FOREACH(it, &sctppcbinfo.iteratorhead, sctp_nxt_itr) {
1968 if (it == inp->inp_starting_point_for_iterator)
1969 /* skip this guy, he's special */
1970 continue;
1971 if (it->inp == inp) {
1972 /*
1973 * This is tricky and we DON'T lock the iterator.
1974 * Reason is he's running but waiting for me since
1975 * inp->inp_starting_point_for_iterator has the lock

--- 412 unchanged lines hidden (view full) ---

2388 /*
2389 * if we have an address list the following will free the list of
2390 * ifaddr's that are set into this ep. Again macro limitations here,
2391 * since the LIST_FOREACH could be a bad idea.
2392 */
2393 for ((laddr = LIST_FIRST(&inp->sctp_addr_list)); laddr != NULL;
2394 laddr = nladdr) {
2395 nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
2396 LIST_REMOVE(laddr, sctp_nxt_addr);
2397 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
2398 SCTP_DECR_LADDR_COUNT();
2399 }
2400
2401#ifdef SCTP_TRACK_FREED_ASOCS
2402 /* TEMP CODE */
2403 for ((asoc = LIST_FIRST(&inp->sctp_asoc_free_list)); asoc != NULL;
2404 asoc = nasoc) {
2405 nasoc = LIST_NEXT(asoc, sctp_tcblist);
2406 LIST_REMOVE(asoc, sctp_tcblist);

--- 36 unchanged lines hidden (view full) ---

2443
2444
2445/*
2446 * add's a remote endpoint address, done with the INIT/INIT-ACK as well as
2447 * when a ASCONF arrives that adds it. It will also initialize all the cwnd
2448 * stats of stuff.
2449 */
2450int
2451sctp_is_address_on_local_host(struct sockaddr *addr)
2452{
2453 struct ifnet *ifn;
2454 struct ifaddr *ifa;
2455
2456 TAILQ_FOREACH(ifn, &ifnet, if_list) {
2457 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
2458 if (addr->sa_family == ifa->ifa_addr->sa_family) {
2459 /* same family */
2460 if (addr->sa_family == AF_INET) {
2461 struct sockaddr_in *sin, *sin_c;
2462
2463 sin = (struct sockaddr_in *)addr;
2464 sin_c = (struct sockaddr_in *)
2465 ifa->ifa_addr;
2466 if (sin->sin_addr.s_addr ==
2467 sin_c->sin_addr.s_addr) {
2468 /*
2469 * we are on the same
2470 * machine
2471 */
2472 return (1);
2473 }
2474 } else if (addr->sa_family == AF_INET6) {
2475 struct sockaddr_in6 *sin6, *sin_c6;
2476
2477 sin6 = (struct sockaddr_in6 *)addr;
2478 sin_c6 = (struct sockaddr_in6 *)
2479 ifa->ifa_addr;
2480 if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2481 &sin_c6->sin6_addr)) {
2482 /*
2483 * we are on the same
2484 * machine
2485 */
2486 return (1);
2487 }
2488 }
2489 }
2490 }
2491 }
2492 return (0);
2493}
2494
2495int
2496sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
2497 int set_scope, int from)
2498{
2499 /*
2500 * The following is redundant to the same lines in the

--- 48 unchanged lines hidden (view full) ---

2549 if (set_scope) {
2550#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE
2551 stcb->ipv4_local_scope = 1;
2552#else
2553 if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
2554 stcb->asoc.ipv4_local_scope = 1;
2555 }
2556#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */
2557
2558 if (sctp_is_address_on_local_host(newaddr)) {
2559 stcb->asoc.loopback_scope = 1;
2560 stcb->asoc.ipv4_local_scope = 1;
2561 stcb->asoc.local_scope = 1;
2562 stcb->asoc.site_scope = 1;
2563 }
2564 } else {
2565 if (from == SCTP_ADDR_IS_CONFIRMED) {
2566 /* From connectx */
2567 if (sctp_is_address_on_local_host(newaddr)) {
2568 stcb->asoc.loopback_scope = 1;
2569 stcb->asoc.ipv4_local_scope = 1;
2570 stcb->asoc.local_scope = 1;
2571 stcb->asoc.site_scope = 1;
2572 }
2573 }
2574 /* Validate the address is in scope */
2575 if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) &&
2576 (stcb->asoc.ipv4_local_scope == 0)) {
2577 addr_inscope = 0;
2578 }
2579 }
2580 } else if (newaddr->sa_family == AF_INET6) {
2581 struct sockaddr_in6 *sin6;
2582
2583 sin6 = (struct sockaddr_in6 *)newaddr;
2584 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2585 /* Invalid address */
2586 return (-1);
2587 }
2588 /* assure len is set */
2589 sin6->sin6_len = sizeof(struct sockaddr_in6);
2590 if (set_scope) {
2591 if (sctp_is_address_on_local_host(newaddr)) {
2592 stcb->asoc.loopback_scope = 1;
2593 stcb->asoc.local_scope = 1;
2594 stcb->asoc.ipv4_local_scope = 1;
2595 stcb->asoc.site_scope = 1;
2596 } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2597 /*
2598 * If the new destination is a LINK_LOCAL we
2599 * must have common site scope. Don't set
2600 * the local scope since we may not share
2601 * all links, only loopback can do this.

--- 5 unchanged lines hidden (view full) ---

2607 } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
2608 /*
2609 * If the new destination is SITE_LOCAL then
2610 * we must have site scope in common.
2611 */
2612 stcb->asoc.site_scope = 1;
2613 }
2614 } else {
2615 if (from == SCTP_ADDR_IS_CONFIRMED) {
2616 /* From connectx so we check for localhost. */
2617 if (sctp_is_address_on_local_host(newaddr)) {
2618 stcb->asoc.loopback_scope = 1;
2619 stcb->asoc.ipv4_local_scope = 1;
2620 stcb->asoc.local_scope = 1;
2621 stcb->asoc.site_scope = 1;
2622 }
2623 }
2624 /* Validate the address is in scope */
2625 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
2626 (stcb->asoc.loopback_scope == 0)) {
2627 addr_inscope = 0;
2628 } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
2629 (stcb->asoc.local_scope == 0)) {
2630 addr_inscope = 0;
2631 } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&

--- 13 unchanged lines hidden (view full) ---

2645 bzero(net, sizeof(*net));
2646 SCTP_GETTIME_TIMEVAL(&net->start_time);
2647 memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
2648 if (newaddr->sa_family == AF_INET) {
2649 ((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport;
2650 } else if (newaddr->sa_family == AF_INET6) {
2651 ((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport;
2652 }
2653 net->addr_is_local = sctp_is_address_on_local_host(newaddr);
2654 net->failure_threshold = stcb->asoc.def_net_failure;
2655 if (addr_inscope == 0) {
2656 net->dest_state = (SCTP_ADDR_REACHABLE |
2657 SCTP_ADDR_OUT_OF_SCOPE);
2658 } else {
2659 if (from == SCTP_ADDR_IS_CONFIRMED)
2660 /* SCTP_ADDR_IS_CONFIRMED is passed by connect_x */
2661 net->dest_state = SCTP_ADDR_REACHABLE;
2662 else
2663 net->dest_state = SCTP_ADDR_REACHABLE |
2664 SCTP_ADDR_UNCONFIRMED;
2665 }
2666 net->RTO = stcb->asoc.initial_rto;
2667 stcb->asoc.numnets++;
2668 *(&net->ref_count) = 1;
2669 net->tos_flowlabel = 0;
2670#ifdef AF_INET
2671 if (newaddr->sa_family == AF_INET)
2672 net->tos_flowlabel = stcb->asoc.default_tos;
2673#endif
2674#ifdef AF_INET6
2675 if (newaddr->sa_family == AF_INET6)
2676 net->tos_flowlabel = stcb->asoc.default_flowlabel;
2677#endif
2678 /* Init the timer structure */
2679 SCTP_OS_TIMER_INIT(&net->rxt_timer.timer);
2680 SCTP_OS_TIMER_INIT(&net->fr_timer.timer);
2681 SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer);
2682

--- 27 unchanged lines hidden (view full) ---

2710
2711 if (stcb->asoc.smallest_mtu > net->mtu) {
2712 stcb->asoc.smallest_mtu = net->mtu;
2713 }
2714 /*
2715 * We take the max of the burst limit times a MTU or the
2716 * INITIAL_CWND. We then limit this to 4 MTU's of sending.
2717 */
2718 net->cwnd = min((net->mtu * 4), max((2 * net->mtu), SCTP_INITIAL_CWND));
2719
2720 /* we always get at LEAST 2 MTU's */
2721 if (net->cwnd < (2 * net->mtu)) {
2722 net->cwnd = 2 * net->mtu;
2723 }
2724 net->ssthresh = stcb->asoc.peers_rwnd;
2725
2726#if defined(SCTP_CWND_MONITOR) || defined(SCTP_CWND_LOGGING)
2727 sctp_log_cwnd(stcb, net, 0, SCTP_CWND_INITIALIZATION);
2728#endif
2729
2730 /*
2731 * CMT: CUC algo - set find_pseudo_cumack to TRUE (1) at beginning
2732 * of assoc (2005/06/27, iyengar@cis.udel.edu)

--- 82 unchanged lines hidden (view full) ---

2815
2816/*
2817 * allocate an association and add it to the endpoint. The caller must be
2818 * careful to add all additional addresses once they are know right away or
2819 * else the assoc will be may experience a blackout scenario.
2820 */
2821struct sctp_tcb *
2822sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
2823 int for_a_init, int *error, uint32_t override_tag)
2824{
2825 struct sctp_tcb *stcb;
2826 struct sctp_association *asoc;
2827 struct sctpasochead *head;
2828 uint16_t rport;
2829 int err;
2830
2831 /*

--- 83 unchanged lines hidden (view full) ---

2915
2916 bzero(stcb, sizeof(*stcb));
2917 asoc = &stcb->asoc;
2918 SCTP_TCB_LOCK_INIT(stcb);
2919 SCTP_TCB_SEND_LOCK_INIT(stcb);
2920 /* setup back pointer's */
2921 stcb->sctp_ep = inp;
2922 stcb->sctp_socket = inp->sctp_socket;
2923 if ((err = sctp_init_asoc(inp, asoc, for_a_init, override_tag))) {
2924 /* failed */
2925 SCTP_TCB_LOCK_DESTROY(stcb);
2926 SCTP_TCB_SEND_LOCK_DESTROY(stcb);
2927 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_asoc, stcb);
2928 SCTP_DECR_ASOC_COUNT();
2929 *error = err;
2930 return (NULL);
2931 }

--- 64 unchanged lines hidden (view full) ---

2996void
2997sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net)
2998{
2999 struct sctp_association *asoc;
3000
3001 asoc = &stcb->asoc;
3002 asoc->numnets--;
3003 TAILQ_REMOVE(&asoc->nets, net, sctp_next);
3004 sctp_free_remote_addr(net);
3005 if (net == asoc->primary_destination) {
3006 /* Reset primary */
3007 struct sctp_nets *lnet;
3008
3009 lnet = TAILQ_FIRST(&asoc->nets);
3010 /* Try to find a confirmed primary */
3011 asoc->primary_destination = sctp_find_alternate_net(stcb, lnet,
3012 0);
3013 }
3014 if (net == asoc->last_data_chunk_from) {
3015 /* Reset primary */
3016 asoc->last_data_chunk_from = TAILQ_FIRST(&asoc->nets);
3017 }
3018 if (net == asoc->last_control_chunk_from) {
3019 /* Clear net */
3020 asoc->last_control_chunk_from = NULL;
3021 }
3022/* if (net == asoc->asconf_last_sent_to) {*/
3023 /* Reset primary */
3024/* asoc->asconf_last_sent_to = TAILQ_FIRST(&asoc->nets);*/
3025/* }*/
3026}
3027
3028/*
3029 * remove a remote endpoint address from an association, it will fail if the
3030 * address does not exist.
3031 */
3032int
3033sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)

--- 592 unchanged lines hidden (view full) ---

3626#endif
3627 break;
3628 }
3629 prev = net;
3630 TAILQ_REMOVE(&asoc->nets, net, sctp_next);
3631 sctp_free_remote_addr(net);
3632 }
3633
3634 /* local addresses, if any */
3635 while (!SCTP_LIST_EMPTY(&asoc->sctp_local_addr_list)) {
3636 laddr = LIST_FIRST(&asoc->sctp_local_addr_list);
3637 LIST_REMOVE(laddr, sctp_nxt_addr);
3638 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
3639 SCTP_DECR_LADDR_COUNT();
3640 }
3641 /* pending asconf (address) parameters */
3642 while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
3643 aparam = TAILQ_FIRST(&asoc->asconf_queue);
3644 TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
3645 SCTP_FREE(aparam);
3646 }
3647 if (asoc->last_asconf_ack_sent != NULL) {
3648 sctp_m_freem(asoc->last_asconf_ack_sent);

--- 137 unchanged lines hidden (view full) ---

3786 if (laddr->ifa == NULL) {
3787#ifdef SCTP_DEBUG
3788 if (sctp_debug_on & SCTP_DEBUG_PCB1) {
3789 printf("An ounce of prevention is worth a pound of cure\n");
3790 }
3791#endif /* SCTP_DEBUG */
3792 continue;
3793 }
3794 if (laddr->ifa->ifa_addr) {
3795 continue;
3796 }
3797 if (laddr->ifa->ifa_addr->sa_family == AF_INET6) {
3798 inp->ip_inp.inp.inp_vflag |= INP_IPV6;
3799 } else if (laddr->ifa->ifa_addr->sa_family == AF_INET) {
3800 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
3801 }
3802 }
3803}
3804
3805/*
3806 * Add the address to the endpoint local address list There is nothing to be
3807 * done if we are bound to all addresses
3808 */
3809int
3810sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct ifaddr *ifa)
3811{
3812 struct sctp_laddr *laddr;
3813 int fnd, error;
3814
3815 fnd = 0;
3816
3817 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3818 /* You are already bound to all. You have it already */
3819 return (0);
3820 }
3821 if (ifa->ifa_addr->sa_family == AF_INET6) {
3822 struct in6_ifaddr *ifa6;
3823
3824 ifa6 = (struct in6_ifaddr *)ifa;
3825 if (ifa6->ia6_flags & (IN6_IFF_DETACHED |
3826 IN6_IFF_DEPRECATED | IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))
3827 /* Can't bind a non-existent addr. */
3828 return (-1);
3829 }
3830 /* first, is it already present? */
3831 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
3832 if (laddr->ifa == ifa) {
3833 fnd = 1;
3834 break;
3835 }
3836 }
3837
3838 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && (fnd == 0)) {
3839 /* Not bound to all */
3840 error = sctp_insert_laddr(&inp->sctp_addr_list, ifa);
3841 if (error != 0)
3842 return (error);
3843 inp->laddr_count++;
3844 /* update inp_vflag flags */
3845 if (ifa->ifa_addr->sa_family == AF_INET6) {
3846 inp->ip_inp.inp.inp_vflag |= INP_IPV6;
3847 } else if (ifa->ifa_addr->sa_family == AF_INET) {
3848 inp->ip_inp.inp.inp_vflag |= INP_IPV4;
3849 }
3850 }
3851 return (0);
3852}
3853
3854
3855/*

--- 20 unchanged lines hidden (view full) ---

3876}
3877
3878
3879/*
3880 * Delete the address from the endpoint local address list There is nothing
3881 * to be done if we are bound to all addresses
3882 */
3883int
3884sctp_del_local_addr_ep(struct sctp_inpcb *inp, struct ifaddr *ifa)
3885{
3886 struct sctp_laddr *laddr;
3887 int fnd;
3888
3889 fnd = 0;
3890 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3891 /* You are already bound to all. You have it already */
3892 return (EINVAL);
3893 }
3894 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
3895 if (laddr->ifa == ifa) {
3896 fnd = 1;
3897 break;
3898 }
3899 }
3900 if (fnd && (inp->laddr_count < 2)) {
3901 /* can't delete unless there are at LEAST 2 addresses */
3902 return (-1);
3903 }
3904 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && (fnd)) {
3905 /*
3906 * clean up any use of this address go through our
3907 * associations and clear any last_used_address that match
3908 * this one for each assoc, see if a new primary_destination
3909 * is needed
3910 */
3911 struct sctp_tcb *stcb;
3912
3913 /* clean up "next_addr_touse" */
3914 if (inp->next_addr_touse == laddr)
3915 /* delete this address */
3916 inp->next_addr_touse = NULL;
3917
3918 /* clean up "last_used_address" */
3919 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3920 if (stcb->asoc.last_used_address == laddr)
3921 /* delete this address */
3922 stcb->asoc.last_used_address = NULL;
3923 } /* for each tcb */
3924
3925 /* remove it from the ep list */
3926 sctp_remove_laddr(laddr);
3927 inp->laddr_count--;
3928 /* update inp_vflag flags */
3929 sctp_update_ep_vflag(inp);
3930 /* select a new primary destination if needed */
3931 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3932 /*
3933 * presume caller (sctp_asconf.c) already owns INP
3934 * lock
3935 */
3936 SCTP_TCB_LOCK(stcb);
3937 if (sctp_destination_is_reachable(stcb,
3938 (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr) == 0) {
3939 sctp_select_primary_destination(stcb);
3940 }
3941 SCTP_TCB_UNLOCK(stcb);
3942 } /* for each tcb */
3943 }
3944 return (0);
3945}
3946
3947/*
3948 * Add the addr to the TCB local address list For the BOUNDALL or dynamic
3949 * case, this is a "pending" address list (eg. addresses waiting for an
3950 * ASCONF-ACK response) For the subset binding, static case, this is a
3951 * "valid" address list
3952 */
3953int
3954sctp_add_local_addr_assoc(struct sctp_tcb *stcb, struct ifaddr *ifa)
3955{
3956 struct sctp_inpcb *inp;
3957 struct sctp_laddr *laddr;
3958 int error;
3959
3960 /*
3961 * Assumes TCP is locked.. and possiblye the INP. May need to
3962 * confirm/fix that if we need it and is not the case.
3963 */
3964 inp = stcb->sctp_ep;
3965 if (ifa->ifa_addr->sa_family == AF_INET6) {
3966 struct in6_ifaddr *ifa6;
3967
3968 ifa6 = (struct in6_ifaddr *)ifa;
3969 if (ifa6->ia6_flags & (IN6_IFF_DETACHED |
3970 /* IN6_IFF_DEPRECATED | */
3971 IN6_IFF_ANYCAST |
3972 IN6_IFF_NOTREADY))
3973 /* Can't bind a non-existent addr. */
3974 return (-1);
3975 }
3976 /* does the address already exist? */
3977 LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr) {
3978 if (laddr->ifa == ifa) {
3979 return (-1);
3980 }
3981 }
3982
3983 /* add to the list */
3984 error = sctp_insert_laddr(&stcb->asoc.sctp_local_addr_list, ifa);
3985 if (error != 0)
3986 return (error);
3987 return (0);
3988}
3989
3990/*
3991 * insert an laddr entry with the given ifa for the desired list
3992 */
3993int
3994sctp_insert_laddr(struct sctpladdr *list, struct ifaddr *ifa)
3995{
3996 struct sctp_laddr *laddr;
3997
3998 laddr = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
3999 if (laddr == NULL) {
4000 /* out of memory? */
4001 return (EINVAL);
4002 }
4003 SCTP_INCR_LADDR_COUNT();
4004 bzero(laddr, sizeof(*laddr));
4005 laddr->ifa = ifa;
4006 /* insert it */
4007 LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr);
4008
4009 return (0);
4010}
4011
4012/*
4013 * Remove an laddr entry from the local address list (on an assoc)
4014 */
4015void
4016sctp_remove_laddr(struct sctp_laddr *laddr)
4017{
4018
4019 /* remove from the list */
4020 LIST_REMOVE(laddr, sctp_nxt_addr);
4021 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, laddr);
4022 SCTP_DECR_LADDR_COUNT();
4023}
4024
4025/*
4026 * Remove an address from the TCB local address list
4027 */
4028int
4029sctp_del_local_addr_assoc(struct sctp_tcb *stcb, struct ifaddr *ifa)
4030{
4031 struct sctp_inpcb *inp;
4032 struct sctp_laddr *laddr;
4033
4034 /*
4035 * This is called by asconf work. It is assumed that a) The TCB is
4036 * locked and b) The INP is locked. This is true in as much as I can
4037 * trace through the entry asconf code where I did these locks.

--- 7 unchanged lines hidden (view full) ---

4045 /* if subset bound and don't allow ASCONF's, can't delete last */
4046 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) &&
4047 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF) == 0)) {
4048 if (stcb->asoc.numnets < 2) {
4049 /* can't delete last address */
4050 return (-1);
4051 }
4052 }
4053 LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr) {
4054 /* remove the address if it exists */
4055 if (laddr->ifa == NULL)
4056 continue;
4057 if (laddr->ifa == ifa) {
4058 sctp_remove_laddr(laddr);
4059 return (0);
4060 }
4061 }
4062
4063 /* address not found! */
4064 return (-1);
4065}
4066
4067/*
4068 * Remove an address from the TCB local address list lookup using a sockaddr
4069 * addr
4070 */
4071int
4072sctp_del_local_addr_assoc_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
4073{
4074 struct sctp_inpcb *inp;
4075 struct sctp_laddr *laddr;
4076 struct sockaddr *l_sa;
4077
4078 /*
4079 * This function I find does not seem to have a caller. As such we
4080 * NEED TO DELETE this code. If we do find a caller, the caller MUST
4081 * have locked the TCB at the least and probably the INP as well.
4082 */
4083 inp = stcb->sctp_ep;
4084 /* if subset bound and don't allow ASCONF's, can't delete last */
4085 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) &&
4086 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF) == 0)) {
4087 if (stcb->asoc.numnets < 2) {
4088 /* can't delete last address */
4089 return (-1);
4090 }
4091 }
4092 LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list, sctp_nxt_addr) {
4093 /* make sure the address exists */
4094 if (laddr->ifa == NULL)
4095 continue;
4096 if (laddr->ifa->ifa_addr == NULL)
4097 continue;
4098
4099 l_sa = laddr->ifa->ifa_addr;
4100 if (l_sa->sa_family == AF_INET6) {
4101 /* IPv6 address */
4102 struct sockaddr_in6 *sin1, *sin2;
4103
4104 sin1 = (struct sockaddr_in6 *)l_sa;
4105 sin2 = (struct sockaddr_in6 *)sa;
4106 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
4107 sizeof(struct in6_addr)) == 0) {
4108 /* matched */
4109 sctp_remove_laddr(laddr);
4110 return (0);
4111 }
4112 } else if (l_sa->sa_family == AF_INET) {
4113 /* IPv4 address */
4114 struct sockaddr_in *sin1, *sin2;
4115
4116 sin1 = (struct sockaddr_in *)l_sa;
4117 sin2 = (struct sockaddr_in *)sa;
4118 if (sin1->sin_addr.s_addr == sin2->sin_addr.s_addr) {
4119 /* matched */
4120 sctp_remove_laddr(laddr);
4121 return (0);
4122 }
4123 } else {
4124 /* invalid family */
4125 return (-1);
4126 }
4127 } /* end foreach */
4128 /* address not found! */
4129 return (-1);
4130}
4131
4132static char sctp_pcb_initialized = 0;
4133
4134/*
4135 * Temporarily remove for __APPLE__ until we use the Tiger equivalents
4136 */
4137/* sysctl */
4138static int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC;
4139static int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR;

--- 14 unchanged lines hidden (view full) ---

4154 sctp_pcb_initialized = 1;
4155
4156 bzero(&sctpstat, sizeof(struct sctpstat));
4157 SCTP_GETTIME_TIMEVAL(&sctpstat.sctps_discontinuitytime);
4158 /* init the empty list of (All) Endpoints */
4159 LIST_INIT(&sctppcbinfo.listhead);
4160
4161 /* init the iterator head */
4162 LIST_INIT(&sctppcbinfo.iteratorhead);
4163
4164 /* init the hash table of endpoints */
4165 TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &sctp_hashtblsize);
4166 TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &sctp_pcbtblsize);
4167 TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &sctp_chunkscale);
4168 sctppcbinfo.sctp_asochash = SCTP_HASH_INIT((sctp_hashtblsize * 31),
4169 &sctppcbinfo.hashasocmark);
4170 sctppcbinfo.sctp_ephash = SCTP_HASH_INIT(sctp_hashtblsize,
4171 &sctppcbinfo.hashmark);
4172 sctppcbinfo.sctp_tcpephash = SCTP_HASH_INIT(sctp_hashtblsize,
4173 &sctppcbinfo.hashtcpmark);
4174 sctppcbinfo.hashtblsize = sctp_hashtblsize;
4175
4176 /* init the small hash table we use to track restarted asoc's */
4177 sctppcbinfo.sctp_restarthash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE,
4178 &sctppcbinfo.hashrestartmark);
4179
4180 /* init the zones */
4181 /*
4182 * FIX ME: Should check for NULL returns, but if it does fail we are
4183 * doomed to panic anyways... add later maybe.
4184 */
4185 SCTP_ZONE_INIT(sctppcbinfo.ipi_zone_ep, "sctp_ep",
4186 sizeof(struct sctp_inpcb), maxsockets);
4187

--- 22 unchanged lines hidden (view full) ---

4210
4211 /* Master Lock INIT for info structure */
4212 SCTP_INP_INFO_LOCK_INIT();
4213 SCTP_STATLOG_INIT_LOCK();
4214 SCTP_ITERATOR_LOCK_INIT();
4215
4216 SCTP_IPI_COUNT_INIT();
4217 SCTP_IPI_ADDR_INIT();
4218 LIST_INIT(&sctppcbinfo.addr_wq);
4219
4220 /* not sure if we need all the counts */
4221 sctppcbinfo.ipi_count_ep = 0;
4222 /* assoc/tcb zone info */
4223 sctppcbinfo.ipi_count_asoc = 0;
4224 /* local addrlist zone info */
4225 sctppcbinfo.ipi_count_laddr = 0;

--- 13 unchanged lines hidden (view full) ---

4239
4240 SCTP_OS_TIMER_INIT(&sctppcbinfo.addr_wq_timer.timer);
4241
4242 /* Init the TIMEWAIT list */
4243 for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) {
4244 LIST_INIT(&sctppcbinfo.vtag_timewait[i]);
4245 }
4246
4247}
4248
4249
4250int
4251sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
4252 int iphlen, int offset, int limit, struct sctphdr *sh,
4253 struct sockaddr *altsa)
4254{

--- 554 unchanged lines hidden (view full) ---

4809 net = sctp_findnet(stcb, sa);
4810
4811 if (net == NULL) {
4812 /* didn't find the requested primary address! */
4813 return (-1);
4814 } else {
4815 /* set the primary address */
4816 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
4817 /* Must be confirmed */
4818 return (-1);
4819 }
4820 stcb->asoc.primary_destination = net;
4821 net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY;
4822 net = TAILQ_FIRST(&stcb->asoc.nets);
4823 if (net != stcb->asoc.primary_destination) {
4824 /*
4825 * first one on the list is NOT the primary
4826 * sctp_cmpaddr() is much more efficent if the

--- 90 unchanged lines hidden (view full) ---

4917 }
4918 }
4919 /* Not found, ok to use the tag */
4920 SCTP_INP_INFO_WUNLOCK();
4921 return (1);
4922}
4923
4924
4925/*
4926 * Delete the address from the endpoint local address list Lookup using a
4927 * sockaddr address (ie. not an ifaddr)
4928 */
4929int
4930sctp_del_local_addr_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa)
4931{
4932 struct sctp_laddr *laddr;
4933 struct sockaddr *l_sa;
4934 int found = 0;
4935
4936 /*
4937 * Here is another function I cannot find a caller for. As such we
4938 * SHOULD delete it if we have no users. If we find a user that user
4939 * MUST have the INP locked.
4940 *
4941 */
4942
4943 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4944 /* You are already bound to all. You have it already */
4945 return (EINVAL);
4946 }
4947 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4948 /* make sure the address exists */
4949 if (laddr->ifa == NULL)
4950 continue;
4951 if (laddr->ifa->ifa_addr == NULL)
4952 continue;
4953
4954 l_sa = laddr->ifa->ifa_addr;
4955 if (l_sa->sa_family == AF_INET6) {
4956 /* IPv6 address */
4957 struct sockaddr_in6 *sin1, *sin2;
4958
4959 sin1 = (struct sockaddr_in6 *)l_sa;
4960 sin2 = (struct sockaddr_in6 *)sa;
4961 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
4962 sizeof(struct in6_addr)) == 0) {
4963 /* matched */
4964 found = 1;
4965 break;
4966 }
4967 } else if (l_sa->sa_family == AF_INET) {
4968 /* IPv4 address */
4969 struct sockaddr_in *sin1, *sin2;
4970
4971 sin1 = (struct sockaddr_in *)l_sa;
4972 sin2 = (struct sockaddr_in *)sa;
4973 if (sin1->sin_addr.s_addr == sin2->sin_addr.s_addr) {
4974 /* matched */
4975 found = 1;
4976 break;
4977 }
4978 } else {
4979 /* invalid family */
4980 return (-1);
4981 }
4982 }
4983
4984 if (found && inp->laddr_count < 2) {
4985 /* can't delete unless there are at LEAST 2 addresses */
4986 return (-1);
4987 }
4988 if (found && (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
4989 /*
4990 * remove it from the ep list, this should NOT be done until
4991 * its really gone from the interface list and we won't be
4992 * receiving more of these. Probably right away. If we do
4993 * allow a removal of an address from an association
4994 * (sub-set bind) than this should NOT be called until the
4995 * all ASCONF come back from this association.
4996 */
4997 sctp_remove_laddr(laddr);
4998 return (0);
4999 } else {
5000 return (-1);
5001 }
5002}
5003
5004static sctp_assoc_t reneged_asoc_ids[256];
5005static uint8_t reneged_at = 0;
5006
5007extern int sctp_do_drain;
5008
5009static void
5010sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
5011{
5012 /*
5013 * We must hunt this association for MBUF's past the cumack (i.e.
5014 * out of order data that we can renege on).
5015 */

--- 139 unchanged lines hidden (view full) ---

5155 /* Nothing left in map */
5156 memset(asoc->mapping_array, 0, asoc->mapping_array_size);
5157 asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1;
5158 asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
5159 }
5160 asoc->last_revoke_count = cnt;
5161 SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
5162 sctp_send_sack(stcb);
5163 reneged_asoc_ids[reneged_at] = sctp_get_associd(stcb);
5164 reneged_at++;
5165 }
5166 /*
5167 * Another issue, in un-setting the TSN's in the mapping array we
5168 * DID NOT adjust the higest_tsn marker. This will cause one of two
5169 * things to occur. It may cause us to do extra work in checking for
5170 * our mapping array movement. More importantly it may cause us to

--- 33 unchanged lines hidden (view full) ---

5204 * start a new iterator
5205 * iterates through all endpoints and associations based on the pcb_state
5206 * flags and asoc_state. "af" (mandatory) is executed for all matching
5207 * assocs and "ef" (optional) is executed when the iterator completes.
5208 * "inpf" (optional) is executed for each new endpoint as it is being
5209 * iterated through.
5210 */
5211int
5212sctp_initiate_iterator(inp_func inpf, asoc_func af, uint32_t pcb_state,
5213 uint32_t pcb_features, uint32_t asoc_state, void *argp, uint32_t argi,
5214 end_func ef, struct sctp_inpcb *s_inp, uint8_t chunk_output_off)
5215{
5216 struct sctp_iterator *it = NULL;
5217
5218 if (af == NULL) {
5219 return (-1);
5220 }
5221 SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator),
5222 "Iterator");
5223 if (it == NULL) {
5224 return (ENOMEM);
5225 }
5226 memset(it, 0, sizeof(*it));
5227 it->function_assoc = af;
5228 it->function_inp = inpf;
5229 it->function_atend = ef;
5230 it->pointer = argp;
5231 it->val = argi;
5232 it->pcb_flags = pcb_state;
5233 it->pcb_features = pcb_features;
5234 it->asoc_state = asoc_state;
5235 it->no_chunk_output = chunk_output_off;
5236 if (s_inp) {
5237 it->inp = s_inp;
5238 it->iterator_flags = SCTP_ITERATOR_DO_SINGLE_INP;
5239 } else {
5240 SCTP_INP_INFO_RLOCK();
5241 it->inp = LIST_FIRST(&sctppcbinfo.listhead);
5242 SCTP_INP_INFO_RUNLOCK();
5243 it->iterator_flags = SCTP_ITERATOR_DO_ALL_INP;
5244
5245 }
5246 /* Init the timer */
5247 SCTP_OS_TIMER_INIT(&it->tmr.timer);
5248 /* add to the list of all iterators */
5249 SCTP_INP_INFO_WLOCK();
5250 LIST_INSERT_HEAD(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
5251 SCTP_INP_INFO_WUNLOCK();
5252 sctp_timer_start(SCTP_TIMER_TYPE_ITERATOR, (struct sctp_inpcb *)it,
5253 NULL, NULL);
5254 return (0);
5255}