static int unix_accept(struct socket *sock, struct socket *newsock, int flags) { unix_socket *sk=sock->data; unix_socket *newsk, *tsk; struct sk_buff *skb; if(sk->type!=SOCK_STREAM) { return -EOPNOTSUPP; } if(sk->state!=TCP_LISTEN) { return -EINVAL; } newsk=newsock->data; if(sk->protinfo.af_unix.name!=NULL) { newsk->protinfo.af_unix.name=kmalloc(strlen(sk->protinfo.af_unix.name)+1, GFP_KERNEL); if(newsk->protinfo.af_unix.name==NULL) return -ENOMEM; strcpy(newsk->protinfo.af_unix.name, sk->protinfo.af_unix.name); } do { cli(); skb=skb_dequeue(&sk->receive_queue); if(skb==NULL) { if(flags&O_NONBLOCK) { sti(); return -EAGAIN; } interruptible_sleep_on(sk->sleep); if(current->signal & ~current->blocked) { sti(); return -ERESTARTSYS; } sti(); } } while(skb==NULL); tsk=skb->sk; kfree_skb(skb, FREE_WRITE); /* The buffer is just used as a tag */ sk->ack_backlog--; newsk->protinfo.af_unix.other=tsk; tsk->protinfo.af_unix.other=newsk; tsk->state=TCP_ESTABLISHED; newsk->state=TCP_ESTABLISHED; newsk->protinfo.af_unix.locks++; /* Swap lock over */ sk->protinfo.af_unix.locks--; /* Locked to child socket not master */ tsk->protinfo.af_unix.locks++; /* Back lock */ sti(); tsk->state_change(tsk); /* Wake up any sleeping connect */ sock_wake_async(tsk->socket, 0); return 0; }
static void def_callback3(struct sock *sk) { if(!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket, 2); } }
/* * N.B. What happens if we're in here when the socket closes?? */ static void found_data(struct sock *sk) { /* * FIXME: copied from sock_def_readable, it should be a call to * server->data_ready(); */ if(!sk->dead) { wake_up_interruptible(sk->sleep); sock_wake_async(sk->socket,1); } }
/** * sk_stream_write_space - stream socket write_space callback. * @sk: socket * * FIXME: write proper description */ void sk_stream_write_space(struct sock *sk) { struct socket *sock = sk->sk_socket; if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) { clear_bit(SOCK_NOSPACE, &sock->flags); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) wake_up_interruptible(sk->sk_sleep); if (sock->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) sock_wake_async(sock, 2, POLL_OUT); } }
/** * sk_stream_write_space - stream socket write_space callback. * @sk: socket * * FIXME: write proper description */ void sk_stream_write_space(struct sock *sk) { struct socket *sock = sk->sk_socket; struct socket_wq *wq; if (sk_stream_is_writeable(sk) && sock) { clear_bit(SOCK_NOSPACE, &sock->flags); rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (wq_has_sleeper(wq)) wake_up_interruptible_poll(&wq->wait, POLLOUT | POLLWRNORM | POLLWRBAND); if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) sock_wake_async(wq, SOCK_WAKE_SPACE, POLL_OUT); rcu_read_unlock(); } }
static int unix_accept(struct socket *sock, struct socket *newsock, int flags) { struct socket *clientsock; /* * If there aren't any sockets awaiting connection, * then wait for one, unless nonblocking. */ while (!(clientsock = sock->iconn)) { if (flags & O_NONBLOCK) return -EAGAIN; sock->flags |= SO_WAITDATA; interruptible_sleep_on(sock->wait); sock->flags &= ~SO_WAITDATA; if (current->signal /* & ~current->blocked */ ) return -ERESTARTSYS; } /* * Great. Finish the connection relative to server and client, * wake up the client and return the new fd to the server. */ sock->iconn = clientsock->next; clientsock->next = NULL; newsock->conn = clientsock; clientsock->conn = newsock; clientsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED; unix_data_ref(UN_DATA(clientsock)); UN_DATA(newsock)->peerupd = UN_DATA(clientsock); UN_DATA(newsock)->sockaddr_un = UN_DATA(sock)->sockaddr_un; UN_DATA(newsock)->sockaddr_len = UN_DATA(sock)->sockaddr_len; wake_up_interruptible(clientsock->wait); #if 0 sock_wake_async(clientsock, 0); /* Don't need */ #endif return 0; }
/* callback implementation for sk.sk_write_space() * to wakeup sndbuf producers that blocked with smc_tx_wait_memory(). * called under sk_socket lock. */ static void smc_tx_write_space(struct sock *sk) { struct socket *sock = sk->sk_socket; struct smc_sock *smc = smc_sk(sk); struct socket_wq *wq; /* similar to sk_stream_write_space */ if (atomic_read(&smc->conn.sndbuf_space) && sock) { clear_bit(SOCK_NOSPACE, &sock->flags); rcu_read_lock(); wq = rcu_dereference(sk->sk_wq); if (skwq_has_sleeper(wq)) wake_up_interruptible_poll(&wq->wait, EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND); if (wq && wq->fasync_list && !(sk->sk_shutdown & SEND_SHUTDOWN)) sock_wake_async(wq, SOCK_WAKE_SPACE, POLL_OUT); rcu_read_unlock(); } }
static int unix_write(struct socket *sock, char *ubuf, int size, int nonblock) { struct unix_proto_data *pupd; int todo, space; if ((todo = size) <= 0) return 0; if (sock->state != SS_CONNECTED) { if (sock->state == SS_DISCONNECTING) { send_sig(SIGPIPE, current, 1); return -EPIPE; } return -EINVAL; } pupd = UN_DATA(sock)->peerupd; /* safer than sock->conn */ while (!(space = UN_BUF_SPACE(pupd))) { sock->flags |= SO_NOSPACE; if (nonblock) return -EAGAIN; sock->flags &= ~SO_NOSPACE; interruptible_sleep_on(sock->wait); if (current->signal /* & ~current->blocked */ ) return -ERESTARTSYS; if (sock->state == SS_DISCONNECTING) { send_sig(SIGPIPE, current, 1); return -EPIPE; } } /* * Copy from the user's buffer to the write buffer, * watching for wraparound. Then we wake up the reader. */ down(&pupd->sem); do { int part, cando; if (space <= 0) { printk("UNIX: write: SPACE IS NEGATIVE (%d)!!!\n", space); send_sig(SIGKILL, current, 1); return -EPIPE; } /* * We may become disconnected inside this loop, so watch * for it (peerupd is safe until we close). */ if (sock->state == SS_DISCONNECTING) { send_sig(SIGPIPE, current, 1); up(&pupd->sem); return -EPIPE; } if ((cando = todo) > space) cando = space; if (cando > (part = UN_BUF_SIZE - pupd->bp_head)) cando = part; memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando); pupd->bp_head = (pupd->bp_head + cando) & (UN_BUF_SIZE - 1); ubuf += cando; todo -= cando; if (sock->state == SS_CONNECTED) { wake_up_interruptible(sock->conn->wait); #if 0 sock_wake_async(sock->conn, 1); #endif } space = UN_BUF_SPACE(pupd); } while (todo && space); up(&pupd->sem); return (size - todo); }
static int unix_read(struct socket *sock, char *ubuf, int size, int nonblock) { struct unix_proto_data *upd; int todo, avail; if ((todo = size) <= 0) return 0; upd = UN_DATA(sock); while (!(avail = UN_BUF_AVAIL(upd))) { if (sock->state != SS_CONNECTED) return ((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL); if (nonblock) return -EAGAIN; sock->flags |= SO_WAITDATA; interruptible_sleep_on(sock->wait); sock->flags &= ~SO_WAITDATA; if (current->signal /* & ~current->blocked */ ) return -ERESTARTSYS; } /* * Copy from the read buffer into the user's buffer, * watching for wraparound. Then we wake up the writer. */ down(&upd->sem); do { int part, cando; if (avail <= 0) { printk("UNIX: read: AVAIL IS NEGATIVE (%d)!!!\n", avail); send_sig(SIGKILL, current, 1); return -EPIPE; } if ((cando = todo) > avail) cando = avail; if (cando > (part = UN_BUF_SIZE - upd->bp_tail)) cando = part; memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando); upd->bp_tail = (upd->bp_tail + cando) & (UN_BUF_SIZE - 1); ubuf += cando; todo -= cando; if (sock->state == SS_CONNECTED) { wake_up_interruptible(sock->conn->wait); #if 0 sock_wake_async(sock->conn, 2); #endif } avail = UN_BUF_AVAIL(upd); } while (todo && avail); up(&upd->sem); return (size - todo); }
/* * State machine for state 3, Connected State. * The handling of the timer(s) is in file x25_timer.c * Handling of state 0 and connection release is in af_x25.c. */ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m) { int queued = 0; int modulus; modulus = (sk->protinfo.x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS; switch (frametype) { case X25_RESET_REQUEST: x25_write_internal(sk, X25_RESET_CONFIRMATION); x25_stop_timer(sk); sk->protinfo.x25->condition = 0x00; sk->protinfo.x25->vs = 0; sk->protinfo.x25->vr = 0; sk->protinfo.x25->va = 0; sk->protinfo.x25->vl = 0; x25_requeue_frames(sk); break; case X25_CLEAR_REQUEST: x25_write_internal(sk, X25_CLEAR_CONFIRMATION); x25_disconnect(sk, 0, skb->data[3], skb->data[4]); break; case X25_RR: case X25_RNR: if (!x25_validate_nr(sk, nr)) { x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); sk->protinfo.x25->condition = 0x00; sk->protinfo.x25->vs = 0; sk->protinfo.x25->vr = 0; sk->protinfo.x25->va = 0; sk->protinfo.x25->vl = 0; sk->protinfo.x25->state = X25_STATE_4; } else { x25_frames_acked(sk, nr); if (frametype == X25_RNR) { sk->protinfo.x25->condition |= X25_COND_PEER_RX_BUSY; } else { sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; } } break; case X25_DATA: /* XXX */ sk->protinfo.x25->condition &= ~X25_COND_PEER_RX_BUSY; if ((ns!=sk->protinfo.x25->vr) || !x25_validate_nr(sk, nr)) { x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); sk->protinfo.x25->condition = 0x00; sk->protinfo.x25->vs = 0; sk->protinfo.x25->vr = 0; sk->protinfo.x25->va = 0; sk->protinfo.x25->vl = 0; sk->protinfo.x25->state = X25_STATE_4; break; } x25_frames_acked(sk, nr); if (ns == sk->protinfo.x25->vr) { if (x25_queue_rx_frame(sk, skb, m) == 0) { sk->protinfo.x25->vr = (sk->protinfo.x25->vr + 1) % modulus; queued = 1; } else { /* Should never happen */ x25_clear_queues(sk); x25_write_internal(sk, X25_RESET_REQUEST); x25_start_t22timer(sk); sk->protinfo.x25->condition = 0x00; sk->protinfo.x25->vs = 0; sk->protinfo.x25->vr = 0; sk->protinfo.x25->va = 0; sk->protinfo.x25->vl = 0; sk->protinfo.x25->state = X25_STATE_4; break; } if (atomic_read(&sk->rmem_alloc) > (sk->rcvbuf / 2)) sk->protinfo.x25->condition |= X25_COND_OWN_RX_BUSY; } /* * If the window is full Ack it immediately, else * start the holdback timer. */ if (((sk->protinfo.x25->vl + sk->protinfo.x25->facilities.winsize_in) % modulus) == sk->protinfo.x25->vr) { sk->protinfo.x25->condition &= ~X25_COND_ACK_PENDING; x25_stop_timer(sk); x25_enquiry_response(sk); } else { sk->protinfo.x25->condition |= X25_COND_ACK_PENDING; x25_start_t2timer(sk); } break; case X25_INTERRUPT_CONFIRMATION: sk->protinfo.x25->intflag = 0; break; case X25_INTERRUPT: if (sk->urginline) { queued = (sock_queue_rcv_skb(sk, skb) == 0); } else { skb_set_owner_r(skb, sk); skb_queue_tail(&sk->protinfo.x25->interrupt_in_queue, skb); queued = 1; } if (sk->proc != 0) { if (sk->proc > 0) kill_proc(sk->proc, SIGURG, 1); else kill_pg(-sk->proc, SIGURG, 1); sock_wake_async(sk->socket, 3, POLL_PRI); } x25_write_internal(sk, X25_INTERRUPT_CONFIRMATION); break; default: printk(KERN_WARNING "x25: unknown %02X in state 3\n", frametype); break; } return queued; }