sctp_peeloff.c (b652778e426d00b6a1df29bbd86869db86f36e25) | sctp_peeloff.c (a3158782c2d7e3a64a1d7ebb77bf42a4596808ce) |
---|---|
1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * --- 137 unchanged lines hidden (view full) --- 146 atomic_add_int(&stcb->asoc.refcnt, 1); 147 SCTP_TCB_UNLOCK(stcb); 148 149 sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT); 150 atomic_subtract_int(&stcb->asoc.refcnt, 1); 151 152 return (0); 153} | 1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * --- 137 unchanged lines hidden (view full) --- 146 atomic_add_int(&stcb->asoc.refcnt, 1); 147 SCTP_TCB_UNLOCK(stcb); 148 149 sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT); 150 atomic_subtract_int(&stcb->asoc.refcnt, 1); 151 152 return (0); 153} |
154 155 156struct socket * 157sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) 158{ 159 struct socket *newso; 160 struct sctp_inpcb *inp, *n_inp; 161 struct sctp_tcb *stcb; 162 163 SCTPDBG(SCTP_DEBUG_PEEL1, "SCTP peel-off called\n"); 164 inp = (struct sctp_inpcb *)head->so_pcb; 165 if (inp == NULL) { 166 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, EFAULT); 167 *error = EFAULT; 168 return (NULL); 169 } 170 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); 171 if (stcb == NULL) { 172 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN); 173 *error = ENOTCONN; 174 return (NULL); 175 } 176 atomic_add_int(&stcb->asoc.refcnt, 1); 177 SCTP_TCB_UNLOCK(stcb); 178 CURVNET_SET(head->so_vnet); 179 newso = sonewconn(head, SS_ISCONNECTED 180 ); 181 CURVNET_RESTORE(); 182 if (newso == NULL) { 183 SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n"); 184 SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM); 185 *error = ENOMEM; 186 atomic_subtract_int(&stcb->asoc.refcnt, 1); 187 return (NULL); 188 189 } 190 SCTP_TCB_LOCK(stcb); 191 atomic_subtract_int(&stcb->asoc.refcnt, 1); 192 n_inp = (struct sctp_inpcb *)newso->so_pcb; 193 SOCK_LOCK(head); 194 n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | 195 SCTP_PCB_FLAGS_CONNECTED | 196 SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */ 197 (SCTP_PCB_COPY_FLAGS & inp->sctp_flags)); 198 n_inp->sctp_features = inp->sctp_features; 199 n_inp->sctp_frag_point = inp->sctp_frag_point; 200 n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off; 201 n_inp->sctp_ecn_enable = inp->sctp_ecn_enable; 202 n_inp->partial_delivery_point = inp->partial_delivery_point; 203 n_inp->sctp_context = inp->sctp_context; 204 n_inp->local_strreset_support = inp->local_strreset_support; 205 n_inp->inp_starting_point_for_iterator = NULL; 206 207 /* copy in the authentication parameters from the original endpoint */ 208 if (n_inp->sctp_ep.local_hmacs) 209 sctp_free_hmaclist(n_inp->sctp_ep.local_hmacs); 210 n_inp->sctp_ep.local_hmacs = 211 sctp_copy_hmaclist(inp->sctp_ep.local_hmacs); 212 if (n_inp->sctp_ep.local_auth_chunks) 213 sctp_free_chunklist(n_inp->sctp_ep.local_auth_chunks); 214 n_inp->sctp_ep.local_auth_chunks = 215 sctp_copy_chunklist(inp->sctp_ep.local_auth_chunks); 216 (void)sctp_copy_skeylist(&inp->sctp_ep.shared_keys, 217 &n_inp->sctp_ep.shared_keys); 218 219 n_inp->sctp_socket = newso; 220 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 221 sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE); 222 n_inp->sctp_ep.auto_close_time = 0; 223 sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL, 224 SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1); 225 } 226 /* Turn off any non-blocking semantic. */ 227 SCTP_CLEAR_SO_NBIO(newso); 228 newso->so_state |= SS_ISCONNECTED; 229 /* We remove it right away */ 230 231#ifdef SCTP_LOCK_LOGGING 232 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) { 233 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK); 234 } 235#endif 236 TAILQ_REMOVE(&head->so_comp, newso, so_list); 237 head->so_qlen--; 238 SOCK_UNLOCK(head); 239 /* 240 * Now we must move it from one hash table to another and get the 241 * stcb in the right place. 242 */ 243 sctp_move_pcb_and_assoc(inp, n_inp, stcb); 244 atomic_add_int(&stcb->asoc.refcnt, 1); 245 SCTP_TCB_UNLOCK(stcb); 246 /* 247 * And now the final hack. We move data in the pending side i.e. 248 * head to the new socket buffer. Let the GRUBBING begin :-0 249 */ 250 sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, SBL_WAIT); 251 atomic_subtract_int(&stcb->asoc.refcnt, 1); 252 return (newso); 253} | |