sctp_pcb.c (171440) | sctp_pcb.c (171477) |
---|---|
1/*- 2 * Copyright (c) 2001-2007, by 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> | 1/*- 2 * Copyright (c) 2001-2007, by 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 171440 2007-07-14 09:36:28Z rrs $"); | 34__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 171477 2007-07-17 20:58:26Z rrs $"); |
35 36#include <netinet/sctp_os.h> 37#include <sys/proc.h> 38#include <netinet/sctp_var.h> 39#include <netinet/sctp_sysctl.h> 40#include <netinet/sctp_pcb.h> 41#include <netinet/sctputil.h> 42#include <netinet/sctp.h> --- 2077 unchanged lines hidden (view full) --- 2120 } 2121 return (0); 2122} 2123 2124 2125 2126int 2127sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, | 35 36#include <netinet/sctp_os.h> 37#include <sys/proc.h> 38#include <netinet/sctp_var.h> 39#include <netinet/sctp_sysctl.h> 40#include <netinet/sctp_pcb.h> 41#include <netinet/sctputil.h> 42#include <netinet/sctp.h> --- 2077 unchanged lines hidden (view full) --- 2120 } 2121 return (0); 2122} 2123 2124 2125 2126int 2127sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, |
2128 struct sctp_ifa *sctp_ifap, struct thread *p) | 2128 struct thread *p) |
2129{ 2130 /* bind a ep to a socket address */ 2131 struct sctppcbhead *head; 2132 struct sctp_inpcb *inp, *inp_tmp; 2133 struct inpcb *ip_inp; 2134 int bindall; | 2129{ 2130 /* bind a ep to a socket address */ 2131 struct sctppcbhead *head; 2132 struct sctp_inpcb *inp, *inp_tmp; 2133 struct inpcb *ip_inp; 2134 int bindall; |
2135 int prison = 0; |
|
2135 uint16_t lport; 2136 int error; 2137 uint32_t vrf_id; 2138 2139 lport = 0; 2140 error = 0; 2141 bindall = 1; 2142 inp = (struct sctp_inpcb *)so->so_pcb; --- 5 unchanged lines hidden (view full) --- 2148 SCTPDBG(SCTP_DEBUG_PCB1, "Addr :"); 2149 SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 2150 } 2151#endif 2152 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { 2153 /* already did a bind, subsequent binds NOT allowed ! */ 2154 return (EINVAL); 2155 } | 2136 uint16_t lport; 2137 int error; 2138 uint32_t vrf_id; 2139 2140 lport = 0; 2141 error = 0; 2142 bindall = 1; 2143 inp = (struct sctp_inpcb *)so->so_pcb; --- 5 unchanged lines hidden (view full) --- 2149 SCTPDBG(SCTP_DEBUG_PCB1, "Addr :"); 2150 SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 2151 } 2152#endif 2153 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { 2154 /* already did a bind, subsequent binds NOT allowed ! */ 2155 return (EINVAL); 2156 } |
2157 if (jailed(p->td_ucred)) { 2158 prison = 1; 2159 } |
|
2156 if (addr != NULL) { 2157 if (addr->sa_family == AF_INET) { 2158 struct sockaddr_in *sin; 2159 2160 /* IPV6_V6ONLY socket? */ 2161 if (SCTP_IPV6_V6ONLY(ip_inp)) { 2162 return (EINVAL); 2163 } 2164 if (addr->sa_len != sizeof(*sin)) 2165 return (EINVAL); 2166 2167 sin = (struct sockaddr_in *)addr; 2168 lport = sin->sin_port; | 2160 if (addr != NULL) { 2161 if (addr->sa_family == AF_INET) { 2162 struct sockaddr_in *sin; 2163 2164 /* IPV6_V6ONLY socket? */ 2165 if (SCTP_IPV6_V6ONLY(ip_inp)) { 2166 return (EINVAL); 2167 } 2168 if (addr->sa_len != sizeof(*sin)) 2169 return (EINVAL); 2170 2171 sin = (struct sockaddr_in *)addr; 2172 lport = sin->sin_port; |
2169 | 2173 if (prison) { 2174 /* 2175 * For INADDR_ANY and LOOPBACK the 2176 * prison_ip() call will tranmute the ip 2177 * address to the proper valie. 2178 */ 2179 if (prison_ip(p->td_ucred, 0, &sin->sin_addr.s_addr)) 2180 return (EINVAL); 2181 } |
2170 if (sin->sin_addr.s_addr != INADDR_ANY) { 2171 bindall = 0; 2172 } 2173 } else if (addr->sa_family == AF_INET6) { 2174 /* Only for pure IPv6 Address. (No IPv4 Mapped!) */ 2175 struct sockaddr_in6 *sin6; 2176 2177 sin6 = (struct sockaddr_in6 *)addr; 2178 2179 if (addr->sa_len != sizeof(*sin6)) 2180 return (EINVAL); 2181 2182 lport = sin6->sin6_port; | 2182 if (sin->sin_addr.s_addr != INADDR_ANY) { 2183 bindall = 0; 2184 } 2185 } else if (addr->sa_family == AF_INET6) { 2186 /* Only for pure IPv6 Address. (No IPv4 Mapped!) */ 2187 struct sockaddr_in6 *sin6; 2188 2189 sin6 = (struct sockaddr_in6 *)addr; 2190 2191 if (addr->sa_len != sizeof(*sin6)) 2192 return (EINVAL); 2193 2194 lport = sin6->sin6_port; |
2195 /* 2196 * Jail checks for IPv6 should go HERE! i.e. add the 2197 * prison_ip() equivilant in this postion to 2198 * transmute the addresses to the proper one jailed. 2199 */ |
|
2183 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2184 bindall = 0; 2185 /* KAME hack: embed scopeid */ 2186 if (sa6_embedscope(sin6, ip6_use_defzone) != 0) 2187 return (EINVAL); 2188 } 2189 /* this must be cleared for ifa_ifwithaddr() */ 2190 sin6->sin6_scope_id = 0; --- 179 unchanged lines hidden (view full) --- 2370 memcpy(sin6, addr, sizeof(struct sockaddr_in6)); 2371 sin6->sin6_port = 0; 2372 } 2373 /* 2374 * first find the interface with the bound address need to 2375 * zero out the port to find the address! yuck! can't do 2376 * this earlier since need port for sctp_pcb_findep() 2377 */ | 2200 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 2201 bindall = 0; 2202 /* KAME hack: embed scopeid */ 2203 if (sa6_embedscope(sin6, ip6_use_defzone) != 0) 2204 return (EINVAL); 2205 } 2206 /* this must be cleared for ifa_ifwithaddr() */ 2207 sin6->sin6_scope_id = 0; --- 179 unchanged lines hidden (view full) --- 2387 memcpy(sin6, addr, sizeof(struct sockaddr_in6)); 2388 sin6->sin6_port = 0; 2389 } 2390 /* 2391 * first find the interface with the bound address need to 2392 * zero out the port to find the address! yuck! can't do 2393 * this earlier since need port for sctp_pcb_findep() 2394 */ |
2378 if (sctp_ifap) 2379 ifa = sctp_ifap; 2380 else 2381 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa, 2382 vrf_id, 0); | 2395 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa, 2396 vrf_id, 0); |
2383 if (ifa == NULL) { 2384 /* Can't find an interface with that address */ 2385 SCTP_INP_WUNLOCK(inp); 2386 SCTP_INP_INFO_WUNLOCK(); 2387 return (EADDRNOTAVAIL); 2388 } 2389 if (addr->sa_family == AF_INET6) { 2390 /* GAK, more FIXME IFA lock? */ --- 982 unchanged lines hidden (view full) --- 3373 } 3374 SCTP_INP_RUNLOCK(inp); 3375 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 3376 /* 3377 * If you have not performed a bind, then we need to do the 3378 * ephemerial bind for you. 3379 */ 3380 if ((err = sctp_inpcb_bind(inp->sctp_socket, | 2397 if (ifa == NULL) { 2398 /* Can't find an interface with that address */ 2399 SCTP_INP_WUNLOCK(inp); 2400 SCTP_INP_INFO_WUNLOCK(); 2401 return (EADDRNOTAVAIL); 2402 } 2403 if (addr->sa_family == AF_INET6) { 2404 /* GAK, more FIXME IFA lock? */ --- 982 unchanged lines hidden (view full) --- 3387 } 3388 SCTP_INP_RUNLOCK(inp); 3389 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 3390 /* 3391 * If you have not performed a bind, then we need to do the 3392 * ephemerial bind for you. 3393 */ 3394 if ((err = sctp_inpcb_bind(inp->sctp_socket, |
3381 (struct sockaddr *)NULL, (struct sctp_ifa *)NULL, | 3395 (struct sockaddr *)NULL, |
3382 (struct thread *)NULL 3383 ))) { 3384 /* bind error, probably perm */ 3385 *error = err; 3386 return (NULL); 3387 } 3388 } 3389 stcb = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_asoc, struct sctp_tcb); --- 1142 unchanged lines hidden (view full) --- 4532 * the INP during its work often times. This must be since we don't 4533 * want other proc's looking up things while what they are looking 4534 * up is changing :-D 4535 */ 4536 4537 inp = stcb->sctp_ep; 4538 /* if subset bound and don't allow ASCONF's, can't delete last */ 4539 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && | 3396 (struct thread *)NULL 3397 ))) { 3398 /* bind error, probably perm */ 3399 *error = err; 3400 return (NULL); 3401 } 3402 } 3403 stcb = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_asoc, struct sctp_tcb); --- 1142 unchanged lines hidden (view full) --- 4546 * the INP during its work often times. This must be since we don't 4547 * want other proc's looking up things while what they are looking 4548 * up is changing :-D 4549 */ 4550 4551 inp = stcb->sctp_ep; 4552 /* if subset bound and don't allow ASCONF's, can't delete last */ 4553 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && |
4540 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF) == 0)) { 4541 if (stcb->asoc.numnets < 2) { | 4554 sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 4555 if (stcb->sctp_ep->laddr_count < 2) { |
4542 /* can't delete last address */ 4543 return; 4544 } 4545 } 4546 LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { 4547 /* remove the address if it exists */ 4548 if (laddr->ifa == NULL) 4549 continue; --- 268 unchanged lines hidden (view full) --- 4818 SCTP_TCB_UNLOCK(stcb_tmp); 4819 return (-3); 4820 } 4821 } 4822 if (stcb->asoc.state == 0) { 4823 /* the assoc was freed? */ 4824 return (-4); 4825 } | 4556 /* can't delete last address */ 4557 return; 4558 } 4559 } 4560 LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { 4561 /* remove the address if it exists */ 4562 if (laddr->ifa == NULL) 4563 continue; --- 268 unchanged lines hidden (view full) --- 4832 SCTP_TCB_UNLOCK(stcb_tmp); 4833 return (-3); 4834 } 4835 } 4836 if (stcb->asoc.state == 0) { 4837 /* the assoc was freed? */ 4838 return (-4); 4839 } |
4840 /* 4841 * peer must explicitly turn this on. This may have been initialized 4842 * to be "on" in order to allow local addr changes while INIT's are 4843 * in flight. 4844 */ 4845 stcb->asoc.peer_supports_asconf = 0; |
|
4826 /* now we must go through each of the params. */ 4827 phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 4828 while (phdr) { 4829 ptype = ntohs(phdr->param_type); 4830 plen = ntohs(phdr->param_length); 4831 /* 4832 * printf("ptype => %0x, plen => %d\n", (uint32_t)ptype, 4833 * (int)plen); --- 847 unchanged lines hidden --- | 4846 /* now we must go through each of the params. */ 4847 phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 4848 while (phdr) { 4849 ptype = ntohs(phdr->param_type); 4850 plen = ntohs(phdr->param_length); 4851 /* 4852 * printf("ptype => %0x, plen => %d\n", (uint32_t)ptype, 4853 * (int)plen); --- 847 unchanged lines hidden --- |