static int auto_connect(struct socket *sock, struct tipc_msg *msg) { struct tipc_sock *tsock = tipc_sk(sock->sk); if (msg_errcode(msg)) { sock->state = SS_DISCONNECTING; return -ECONNREFUSED; } tsock->peer_name.ref = msg_origport(msg); tsock->peer_name.node = msg_orignode(msg); tipc_connect2port(tsock->p->ref, &tsock->peer_name); tipc_set_portimportance(tsock->p->ref, msg_importance(msg)); sock->state = SS_CONNECTED; return 0; }
int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, char *data, u32 sz, u32 *ret_size, struct tipc_portid *orig) { int rv = -EINVAL; u32 cmd = msg->cmd; *ret_size = 0; switch (cmd) { case TIPC_REMOVE_LINK: case TIPC_CMD_BLOCK_LINK: case TIPC_CMD_UNBLOCK_LINK: if (!cfg_check_connection(orig)) rv = link_control(msg->argv.link_name, msg->cmd, 0); break; case TIPC_ESTABLISH: { int connected; tipc_isconnected(mng.conn_port_ref, &connected); if (connected || !orig) { rv = TIPC_FAILURE; break; } rv = tipc_connect2port(mng.conn_port_ref, orig); if (rv == TIPC_OK) orig = 0; break; } case TIPC_GET_PEER_ADDRESS: *ret_size = link_peer_addr(msg->argv.link_name, data, sz); break; case TIPC_GET_ROUTES: rv = TIPC_OK; break; default: {} } if (*ret_size) rv = TIPC_OK; return rv; }
static void cfg_cmd_event(struct tipc_cmd_msg *msg, char *data, u32 sz, struct tipc_portid const *orig) { int rv = -EINVAL; struct tipc_cmd_result_msg rmsg; struct iovec msg_sect[2]; int *arg; msg->cmd = ntohl(msg->cmd); cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, data, 0); if (ntohl(msg->magic) != TIPC_MAGIC) goto exit; switch (msg->cmd) { case TIPC_CREATE_LINK: if (!cfg_check_connection(orig)) rv = disc_create_link(&msg->argv.create_link); break; case TIPC_LINK_SUBSCRIBE: { struct subscr_data *sub; if (mng.link_subscriptions > 64) break; sub = kmalloc(sizeof(*sub), GFP_ATOMIC); if (sub == NULL) { warn("Memory squeeze; dropped remote link subscription\n"); break; } INIT_LIST_HEAD(&sub->subd_list); tipc_createport(mng.user_ref, (void *)sub, TIPC_HIGH_IMPORTANCE, 0, 0, (tipc_conn_shutdown_event)cfg_linksubscr_cancel, 0, 0, (tipc_conn_msg_event)cfg_linksubscr_cancel, 0, &sub->port_ref); if (!sub->port_ref) { kfree(sub); break; } memcpy(sub->usr_handle,msg->usr_handle, sizeof(sub->usr_handle)); sub->domain = msg->argv.domain; list_add_tail(&sub->subd_list, &mng.link_subscribers); tipc_connect2port(sub->port_ref, orig); rmsg.retval = TIPC_OK; tipc_send(sub->port_ref, 2u, msg_sect); mng.link_subscriptions++; return; } default: rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); } exit: rmsg.result_len = htonl(msg_sect[1].iov_len); rmsg.retval = htonl(rv); tipc_cfg_respond(msg_sect, 2u, orig); }
static int accept(struct socket *sock, struct socket *new_sock, int flags) { struct sock *sk = sock->sk; struct sk_buff *buf; int res; lock_sock(sk); if (sock->state != SS_LISTENING) { res = -EINVAL; goto exit; } while (skb_queue_empty(&sk->sk_receive_queue)) { if (flags & O_NONBLOCK) { res = -EWOULDBLOCK; goto exit; } release_sock(sk); res = wait_event_interruptible(*sk_sleep(sk), (!skb_queue_empty(&sk->sk_receive_queue))); lock_sock(sk); if (res) goto exit; } buf = skb_peek(&sk->sk_receive_queue); res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); if (!res) { struct sock *new_sk = new_sock->sk; struct tipc_sock *new_tsock = tipc_sk(new_sk); struct tipc_port *new_tport = new_tsock->p; u32 new_ref = new_tport->ref; struct tipc_msg *msg = buf_msg(buf); lock_sock(new_sk); /* * Reject any stray messages received by new socket * before the socket lock was taken (very, very unlikely) */ reject_rx_queue(new_sk); /* Connect new socket to it's peer */ new_tsock->peer_name.ref = msg_origport(msg); new_tsock->peer_name.node = msg_orignode(msg); tipc_connect2port(new_ref, &new_tsock->peer_name); new_sock->state = SS_CONNECTED; tipc_set_portimportance(new_ref, msg_importance(msg)); if (msg_named(msg)) { new_tport->conn_type = msg_nametype(msg); new_tport->conn_instance = msg_nameinst(msg); } /* * Respond to 'SYN-' by discarding it & returning 'ACK'-. * Respond to 'SYN+' by queuing it on new socket. */ if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; advance_rx_queue(sk); send_packet(NULL, new_sock, &m, 0); } else { __skb_dequeue(&sk->sk_receive_queue); __skb_queue_head(&new_sk->sk_receive_queue, buf); } release_sock(new_sk); } exit: release_sock(sk); return res; }
static int accept(struct socket *sock, struct socket *newsock, int flags) { struct tipc_sock *tsock = tipc_sk(sock->sk); struct sk_buff *buf; int res = -EFAULT; if (sock->state == SS_READY) return -EOPNOTSUPP; if (sock->state != SS_LISTENING) return -EINVAL; if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && (flags & O_NONBLOCK))) return -EWOULDBLOCK; if (down_interruptible(&tsock->sem)) return -ERESTARTSYS; if (wait_event_interruptible(*sock->sk->sk_sleep, skb_queue_len(&sock->sk->sk_receive_queue))) { res = -ERESTARTSYS; goto exit; } buf = skb_peek(&sock->sk->sk_receive_queue); res = tipc_create(newsock, 0); if (!res) { struct tipc_sock *new_tsock = tipc_sk(newsock->sk); struct tipc_portid id; struct tipc_msg *msg = buf_msg(buf); u32 new_ref = new_tsock->p->ref; id.ref = msg_origport(msg); id.node = msg_orignode(msg); tipc_connect2port(new_ref, &id); newsock->state = SS_CONNECTED; tipc_set_portimportance(new_ref, msg_importance(msg)); if (msg_named(msg)) { new_tsock->p->conn_type = msg_nametype(msg); new_tsock->p->conn_instance = msg_nameinst(msg); } /* * Respond to 'SYN-' by discarding it & returning 'ACK'-. * Respond to 'SYN+' by queuing it on new socket. */ msg_dbg(msg,"<ACC<: "); if (!msg_data_sz(msg)) { struct msghdr m = {NULL,}; send_packet(NULL, newsock, &m, 0); advance_queue(tsock); } else { sock_lock(tsock); skb_dequeue(&sock->sk->sk_receive_queue); sock_unlock(tsock); skb_queue_head(&newsock->sk->sk_receive_queue, buf); } } exit: up(&tsock->sem); return res; }