/** * tipc_create - create a TIPC socket * @sock: pre-allocated socket structure * @protocol: protocol indicator (must be 0) * * This routine creates and attaches a 'struct sock' to the 'struct socket', * then create and attaches a TIPC port to the 'struct sock' part. * * Returns 0 on success, errno otherwise */ static int tipc_create(struct socket *sock, int protocol) { struct tipc_sock *tsock; struct tipc_port *port; struct sock *sk; u32 ref; if (unlikely(protocol != 0)) return -EPROTONOSUPPORT; ref = tipc_createport_raw(NULL, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); if (unlikely(!ref)) return -ENOMEM; sock->state = SS_UNCONNECTED; switch (sock->type) { case SOCK_STREAM: sock->ops = &stream_ops; break; case SOCK_SEQPACKET: sock->ops = &packet_ops; break; case SOCK_DGRAM: tipc_set_portunreliable(ref, 1); /* fall through */ case SOCK_RDM: tipc_set_portunreturnable(ref, 1); sock->ops = &msg_ops; sock->state = SS_READY; break; default: tipc_deleteport(ref); return -EPROTOTYPE; } sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); if (!sk) { tipc_deleteport(ref); return -ENOMEM; } sock_init_data(sock, sk); init_waitqueue_head(sk->sk_sleep); sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */ tsock = tipc_sk(sk); port = tipc_get_port(ref); tsock->p = port; port->usr_handle = tsock; init_MUTEX(&tsock->sem); dbg("sock_create: %x\n",tsock); atomic_inc(&tipc_user_count); return 0; }
void tipc_cfg_stop(void) { if (config_port_ref) { tipc_deleteport(config_port_ref); config_port_ref = 0; } }
/** * release - destroy a TIPC socket * @sock: socket to destroy * * This routine cleans up any messages that are still queued on the socket. * For DGRAM and RDM socket types, all queued messages are rejected. * For SEQPACKET and STREAM socket types, the first message is rejected * and any others are discarded. (If the first message on a STREAM socket * is partially-read, it is discarded and the next one is rejected instead.) * * NOTE: Rejected messages are not necessarily returned to the sender! They * are returned or discarded according to the "destination droppable" setting * specified for the message by the sender. * * Returns 0 on success, errno otherwise */ static int release(struct socket *sock) { struct sock *sk = sock->sk; struct tipc_port *tport; struct sk_buff *buf; int res; /* * Exit if socket isn't fully initialized (occurs when a failed accept() * releases a pre-allocated child socket that was never used) */ if (sk == NULL) return 0; tport = tipc_sk_port(sk); lock_sock(sk); /* * Reject all unreceived messages, except on an active connection * (which disconnects locally & sends a 'FIN+' to peer) */ while (sock->state != SS_DISCONNECTING) { buf = __skb_dequeue(&sk->sk_receive_queue); if (buf == NULL) break; atomic_dec(&tipc_queue_size); if (TIPC_SKB_CB(buf)->handle != 0) kfree_skb(buf); else { if ((sock->state == SS_CONNECTING) || (sock->state == SS_CONNECTED)) { sock->state = SS_DISCONNECTING; tipc_disconnect(tport->ref); } tipc_reject_msg(buf, TIPC_ERR_NO_PORT); } } /* * Delete TIPC port; this ensures no more messages are queued * (also disconnects an active connection & sends a 'FIN-' to peer) */ res = tipc_deleteport(tport->ref); /* Discard any remaining (connection-based) messages in receive queue */ discard_rx_queue(sk); /* Reject any messages that accumulated in backlog queue */ sock->state = SS_DISCONNECTING; release_sock(sk); sock_put(sk); sock->sk = NULL; return res; }
static int release(struct socket *sock) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sock *sk = sock->sk; int res = TIPC_OK; struct sk_buff *buf; dbg("sock_delete: %x\n",tsock); if (!tsock) return 0; down_interruptible(&tsock->sem); if (!sock->sk) { up(&tsock->sem); return 0; } /* Reject unreceived messages, unless no longer connected */ while (sock->state != SS_DISCONNECTING) { sock_lock(tsock); buf = skb_dequeue(&sk->sk_receive_queue); if (!buf) tsock->p->usr_handle = NULL; sock_unlock(tsock); if (!buf) break; if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) buf_discard(buf); else tipc_reject_msg(buf, TIPC_ERR_NO_PORT); atomic_dec(&tipc_queue_size); } /* Delete TIPC port */ res = tipc_deleteport(tsock->p->ref); sock->sk = NULL; /* Discard any remaining messages */ while ((buf = skb_dequeue(&sk->sk_receive_queue))) { buf_discard(buf); atomic_dec(&tipc_queue_size); } up(&tsock->sem); sock_put(sk); atomic_dec(&tipc_user_count); return res; }