Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Phonet: receive pipe control requests as out-of-band data

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Rémi Denis-Courmont and committed by
David S. Miller
c41bd97f 9641458d

+52 -19
+2
include/net/phonet/pep.h
··· 33 33 34 34 /* Connected socket stuff: */ 35 35 struct sock *listener; 36 + struct sk_buff_head ctrlreq_queue; 37 + #define PNPIPE_CTRLREQ_MAX 10 36 38 u16 peer_type; /* peer type/subtype */ 37 39 u8 pipe_handle; 38 40
+47 -18
net/phonet/pep.c
··· 137 137 138 138 /* Control requests are not sent by the pipe service and have a specific 139 139 * message format. */ 140 - static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code) 140 + static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code, 141 + gfp_t priority) 141 142 { 142 143 const struct pnpipehdr *oph = pnp_hdr(oskb); 143 144 struct sk_buff *skb; 144 145 struct pnpipehdr *ph; 145 146 struct sockaddr_pn dst; 146 147 147 - skb = alloc_skb(MAX_PNPIPE_HEADER + 4, GFP_ATOMIC); 148 + skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); 148 149 if (!skb) 149 150 return -ENOMEM; 150 151 skb_set_owner_w(skb, sk); ··· 306 305 { 307 306 struct pep_sock *pn = pep_sk(sk); 308 307 struct pnpipehdr *hdr = pnp_hdr(skb); 308 + struct sk_buff_head *queue; 309 309 int err = 0; 310 310 311 311 BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); ··· 347 345 break; 348 346 349 347 case PNS_PEP_CTRL_REQ: 350 - /* TODO */ 351 - pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR); 352 - break; 348 + if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) 349 + break; 350 + __skb_pull(skb, 4); 351 + queue = &pn->ctrlreq_queue; 352 + goto queue; 353 353 354 354 case PNS_PIPE_DATA: 355 355 __skb_pull(skb, 3); /* Pipe data header */ ··· 367 363 break; 368 364 } 369 365 pn->rx_credits--; 370 - skb->dev = NULL; 371 - skb_set_owner_r(skb, sk); 372 - err = skb->len; 373 - skb_queue_tail(&sk->sk_receive_queue, skb); 374 - if (!sock_flag(sk, SOCK_DEAD)) 375 - sk->sk_data_ready(sk, err); 376 - return 0; 366 + queue = &sk->sk_receive_queue; 367 + goto queue; 377 368 378 369 case PNS_PEP_STATUS_IND: 379 370 pipe_rcv_status(sk, skb); ··· 411 412 out: 412 413 kfree_skb(skb); 413 414 return err; 415 + 416 + queue: 417 + skb->dev = NULL; 418 + skb_set_owner_r(skb, sk); 419 + err = skb->len; 420 + skb_queue_tail(queue, skb); 421 + if (!sock_flag(sk, SOCK_DEAD)) 422 + sk->sk_data_ready(sk, err); 423 + return 0; 414 424 } 415 425 416 426 /* Destroy connected sock. */ 417 427 static void pipe_destruct(struct sock *sk) 418 428 { 429 + struct pep_sock *pn = pep_sk(sk); 430 + 419 431 skb_queue_purge(&sk->sk_receive_queue); 432 + skb_queue_purge(&pn->ctrlreq_queue); 420 433 } 421 434 422 435 static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) ··· 501 490 pn_skb_get_dst_sockaddr(skb, &dst); 502 491 newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst); 503 492 newpn->pn_sk.resource = pn->pn_sk.resource; 493 + skb_queue_head_init(&newpn->ctrlreq_queue); 504 494 newpn->pipe_handle = pipe_handle; 505 495 newpn->peer_type = peer_type; 506 496 newpn->rx_credits = newpn->tx_credits = 0; ··· 593 581 break; 594 582 595 583 case PNS_PEP_CTRL_REQ: 596 - pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE); 584 + pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE, GFP_ATOMIC); 597 585 break; 598 586 599 587 case PNS_PEP_RESET_REQ: ··· 696 684 697 685 static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) 698 686 { 687 + struct pep_sock *pn = pep_sk(sk); 699 688 int answ; 700 689 701 690 switch (cmd) { ··· 705 692 return -EINVAL; 706 693 707 694 lock_sock(sk); 708 - if (!skb_queue_empty(&sk->sk_receive_queue)) 695 + if (sock_flag(sk, SOCK_URGINLINE) 696 + && !skb_queue_empty(&pn->ctrlreq_queue)) 697 + answ = skb_peek(&pn->ctrlreq_queue)->len; 698 + else if (!skb_queue_empty(&sk->sk_receive_queue)) 709 699 answ = skb_peek(&sk->sk_receive_queue)->len; 710 700 else 711 701 answ = 0; ··· 725 709 726 710 INIT_HLIST_HEAD(&pn->ackq); 727 711 INIT_HLIST_HEAD(&pn->hlist); 712 + skb_queue_head_init(&pn->ctrlreq_queue); 728 713 pn->pipe_handle = PN_PIPE_INVALID_HANDLE; 729 714 return 0; 730 715 } ··· 827 810 struct sk_buff *skb; 828 811 int err; 829 812 830 - if (unlikely(flags & MSG_OOB)) 831 - return -EOPNOTSUPP; 832 813 if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) 833 814 return -ENOTCONN; 815 + 816 + if ((flags & MSG_OOB) || sock_flag(sk, SOCK_URGINLINE)) { 817 + /* Dequeue and acknowledge control request */ 818 + struct pep_sock *pn = pep_sk(sk); 819 + 820 + skb = skb_dequeue(&pn->ctrlreq_queue); 821 + if (skb) { 822 + pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, 823 + GFP_KERNEL); 824 + msg->msg_flags |= MSG_OOB; 825 + goto copy; 826 + } 827 + if (flags & MSG_OOB) 828 + return -EINVAL; 829 + } 834 830 835 831 skb = skb_recv_datagram(sk, flags, noblock, &err); 836 832 lock_sock(sk); ··· 857 827 if (sk->sk_state == TCP_ESTABLISHED) 858 828 pipe_grant_credits(sk); 859 829 release_sock(sk); 860 - 830 + copy: 861 831 msg->msg_flags |= MSG_EOR; 862 - 863 832 if (skb->len > len) 864 833 msg->msg_flags |= MSG_TRUNC; 865 834 else
+3 -1
net/phonet/socket.c
··· 220 220 221 221 if (!skb_queue_empty(&sk->sk_receive_queue)) 222 222 mask |= POLLIN | POLLRDNORM; 223 - else if (sk->sk_state == TCP_CLOSE_WAIT) 223 + if (!skb_queue_empty(&pn->ctrlreq_queue)) 224 + mask |= POLLPRI; 225 + if (!mask && sk->sk_state == TCP_CLOSE_WAIT) 224 226 return POLLHUP; 225 227 226 228 if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)