| .. | .. |
|---|
| 40 | 40 | #include "socket.h" |
|---|
| 41 | 41 | #include "addr.h" |
|---|
| 42 | 42 | #include "msg.h" |
|---|
| 43 | +#include "bearer.h" |
|---|
| 43 | 44 | #include <net/sock.h> |
|---|
| 44 | 45 | #include <linux/module.h> |
|---|
| 45 | 46 | |
|---|
| .. | .. |
|---|
| 47 | 48 | #define MAX_SEND_MSG_COUNT 25 |
|---|
| 48 | 49 | #define MAX_RECV_MSG_COUNT 25 |
|---|
| 49 | 50 | #define CF_CONNECTED 1 |
|---|
| 50 | | -#define CF_SERVER 2 |
|---|
| 51 | 51 | |
|---|
| 52 | 52 | #define TIPC_SERVER_NAME_LEN 32 |
|---|
| 53 | 53 | |
|---|
| .. | .. |
|---|
| 57 | 57 | * @idr_lock: protect the connection identifier set |
|---|
| 58 | 58 | * @idr_in_use: amount of allocated identifier entry |
|---|
| 59 | 59 | * @net: network namspace instance |
|---|
| 60 | | - * @rcvbuf_cache: memory cache of server receive buffer |
|---|
| 60 | + * @awork: accept work item |
|---|
| 61 | 61 | * @rcv_wq: receive workqueue |
|---|
| 62 | 62 | * @send_wq: send workqueue |
|---|
| 63 | | - * @max_rcvbuf_size: maximum permitted receive message length |
|---|
| 64 | | - * @tipc_conn_new: callback will be called when new connection is incoming |
|---|
| 65 | | - * @tipc_conn_release: callback will be called before releasing the connection |
|---|
| 66 | | - * @tipc_conn_recvmsg: callback will be called when message arrives |
|---|
| 63 | + * @listener: topsrv listener socket |
|---|
| 67 | 64 | * @name: server name |
|---|
| 68 | | - * @imp: message importance |
|---|
| 69 | | - * @type: socket type |
|---|
| 70 | 65 | */ |
|---|
| 71 | 66 | struct tipc_topsrv { |
|---|
| 72 | 67 | struct idr conn_idr; |
|---|
| .. | .. |
|---|
| 76 | 71 | struct work_struct awork; |
|---|
| 77 | 72 | struct workqueue_struct *rcv_wq; |
|---|
| 78 | 73 | struct workqueue_struct *send_wq; |
|---|
| 79 | | - int max_rcvbuf_size; |
|---|
| 80 | 74 | struct socket *listener; |
|---|
| 81 | 75 | char name[TIPC_SERVER_NAME_LEN]; |
|---|
| 82 | 76 | }; |
|---|
| .. | .. |
|---|
| 90 | 84 | * @server: pointer to connected server |
|---|
| 91 | 85 | * @sub_list: lsit to all pertaing subscriptions |
|---|
| 92 | 86 | * @sub_lock: lock protecting the subscription list |
|---|
| 93 | | - * @outqueue_lock: control access to the outqueue |
|---|
| 94 | 87 | * @rwork: receive work item |
|---|
| 95 | | - * @rx_action: what to do when connection socket is active |
|---|
| 96 | 88 | * @outqueue: pointer to first outbound message in queue |
|---|
| 97 | 89 | * @outqueue_lock: control access to the outqueue |
|---|
| 98 | 90 | * @swork: send work item |
|---|
| .. | .. |
|---|
| 184 | 176 | conn_put(con); |
|---|
| 185 | 177 | } |
|---|
| 186 | 178 | |
|---|
| 187 | | -static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) |
|---|
| 179 | +static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *sock) |
|---|
| 188 | 180 | { |
|---|
| 189 | 181 | struct tipc_conn *con; |
|---|
| 190 | 182 | int ret; |
|---|
| .. | .. |
|---|
| 210 | 202 | } |
|---|
| 211 | 203 | con->conid = ret; |
|---|
| 212 | 204 | s->idr_in_use++; |
|---|
| 213 | | - spin_unlock_bh(&s->idr_lock); |
|---|
| 214 | 205 | |
|---|
| 215 | 206 | set_bit(CF_CONNECTED, &con->flags); |
|---|
| 216 | 207 | con->server = s; |
|---|
| 208 | + con->sock = sock; |
|---|
| 209 | + conn_get(con); |
|---|
| 210 | + spin_unlock_bh(&s->idr_lock); |
|---|
| 217 | 211 | |
|---|
| 218 | 212 | return con; |
|---|
| 219 | 213 | } |
|---|
| .. | .. |
|---|
| 244 | 238 | if (!s || !memcmp(s, &sub->evt.s, sizeof(*s))) { |
|---|
| 245 | 239 | tipc_sub_unsubscribe(sub); |
|---|
| 246 | 240 | atomic_dec(&tn->subscription_count); |
|---|
| 247 | | - } else if (s) { |
|---|
| 248 | | - break; |
|---|
| 241 | + if (s) |
|---|
| 242 | + break; |
|---|
| 249 | 243 | } |
|---|
| 250 | 244 | } |
|---|
| 251 | 245 | spin_unlock_bh(&con->sub_lock); |
|---|
| .. | .. |
|---|
| 369 | 363 | { |
|---|
| 370 | 364 | struct tipc_net *tn = tipc_net(srv->net); |
|---|
| 371 | 365 | struct tipc_subscription *sub; |
|---|
| 366 | + u32 s_filter = tipc_sub_read(s, filter); |
|---|
| 372 | 367 | |
|---|
| 373 | | - if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) { |
|---|
| 374 | | - s->filter &= __constant_ntohl(~TIPC_SUB_CANCEL); |
|---|
| 368 | + if (s_filter & TIPC_SUB_CANCEL) { |
|---|
| 369 | + tipc_sub_write(s, filter, s_filter & ~TIPC_SUB_CANCEL); |
|---|
| 375 | 370 | tipc_conn_delete_sub(con, s); |
|---|
| 376 | 371 | return 0; |
|---|
| 377 | 372 | } |
|---|
| .. | .. |
|---|
| 401 | 396 | iov.iov_base = &s; |
|---|
| 402 | 397 | iov.iov_len = sizeof(s); |
|---|
| 403 | 398 | msg.msg_name = NULL; |
|---|
| 404 | | - iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, iov.iov_len); |
|---|
| 399 | + iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, iov.iov_len); |
|---|
| 405 | 400 | ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT); |
|---|
| 406 | 401 | if (ret == -EWOULDBLOCK) |
|---|
| 407 | 402 | return -EWOULDBLOCK; |
|---|
| .. | .. |
|---|
| 457 | 452 | static void tipc_topsrv_accept(struct work_struct *work) |
|---|
| 458 | 453 | { |
|---|
| 459 | 454 | struct tipc_topsrv *srv = container_of(work, struct tipc_topsrv, awork); |
|---|
| 460 | | - struct socket *lsock = srv->listener; |
|---|
| 461 | | - struct socket *newsock; |
|---|
| 455 | + struct socket *newsock, *lsock; |
|---|
| 462 | 456 | struct tipc_conn *con; |
|---|
| 463 | 457 | struct sock *newsk; |
|---|
| 464 | 458 | int ret; |
|---|
| 459 | + |
|---|
| 460 | + spin_lock_bh(&srv->idr_lock); |
|---|
| 461 | + if (!srv->listener) { |
|---|
| 462 | + spin_unlock_bh(&srv->idr_lock); |
|---|
| 463 | + return; |
|---|
| 464 | + } |
|---|
| 465 | + lsock = srv->listener; |
|---|
| 466 | + spin_unlock_bh(&srv->idr_lock); |
|---|
| 465 | 467 | |
|---|
| 466 | 468 | while (1) { |
|---|
| 467 | 469 | ret = kernel_accept(lsock, &newsock, O_NONBLOCK); |
|---|
| 468 | 470 | if (ret < 0) |
|---|
| 469 | 471 | return; |
|---|
| 470 | | - con = tipc_conn_alloc(srv); |
|---|
| 472 | + con = tipc_conn_alloc(srv, newsock); |
|---|
| 471 | 473 | if (IS_ERR(con)) { |
|---|
| 472 | 474 | ret = PTR_ERR(con); |
|---|
| 473 | 475 | sock_release(newsock); |
|---|
| .. | .. |
|---|
| 479 | 481 | newsk->sk_data_ready = tipc_conn_data_ready; |
|---|
| 480 | 482 | newsk->sk_write_space = tipc_conn_write_space; |
|---|
| 481 | 483 | newsk->sk_user_data = con; |
|---|
| 482 | | - con->sock = newsock; |
|---|
| 483 | 484 | write_unlock_bh(&newsk->sk_callback_lock); |
|---|
| 484 | 485 | |
|---|
| 485 | 486 | /* Wake up receive process in case of 'SYN+' message */ |
|---|
| 486 | 487 | newsk->sk_data_ready(newsk); |
|---|
| 488 | + conn_put(con); |
|---|
| 487 | 489 | } |
|---|
| 488 | 490 | } |
|---|
| 489 | 491 | |
|---|
| 490 | | -/* tipc_toprsv_listener_data_ready - interrupt callback with connection request |
|---|
| 492 | +/* tipc_topsrv_listener_data_ready - interrupt callback with connection request |
|---|
| 491 | 493 | * The queued job is launched into tipc_topsrv_accept() |
|---|
| 492 | 494 | */ |
|---|
| 493 | 495 | static void tipc_topsrv_listener_data_ready(struct sock *sk) |
|---|
| .. | .. |
|---|
| 496 | 498 | |
|---|
| 497 | 499 | read_lock_bh(&sk->sk_callback_lock); |
|---|
| 498 | 500 | srv = sk->sk_user_data; |
|---|
| 499 | | - if (srv->listener) |
|---|
| 501 | + if (srv) |
|---|
| 500 | 502 | queue_work(srv->rcv_wq, &srv->awork); |
|---|
| 501 | 503 | read_unlock_bh(&sk->sk_callback_lock); |
|---|
| 502 | 504 | } |
|---|
| 503 | 505 | |
|---|
| 504 | 506 | static int tipc_topsrv_create_listener(struct tipc_topsrv *srv) |
|---|
| 505 | 507 | { |
|---|
| 506 | | - int imp = TIPC_CRITICAL_IMPORTANCE; |
|---|
| 507 | 508 | struct socket *lsock = NULL; |
|---|
| 508 | 509 | struct sockaddr_tipc saddr; |
|---|
| 509 | 510 | struct sock *sk; |
|---|
| .. | .. |
|---|
| 520 | 521 | sk->sk_user_data = srv; |
|---|
| 521 | 522 | write_unlock_bh(&sk->sk_callback_lock); |
|---|
| 522 | 523 | |
|---|
| 523 | | - rc = kernel_setsockopt(lsock, SOL_TIPC, TIPC_IMPORTANCE, |
|---|
| 524 | | - (char *)&imp, sizeof(imp)); |
|---|
| 524 | + lock_sock(sk); |
|---|
| 525 | + rc = tsk_set_importance(sk, TIPC_CRITICAL_IMPORTANCE); |
|---|
| 526 | + release_sock(sk); |
|---|
| 525 | 527 | if (rc < 0) |
|---|
| 526 | 528 | goto err; |
|---|
| 527 | 529 | |
|---|
| .. | .. |
|---|
| 575 | 577 | sub.seq.upper = upper; |
|---|
| 576 | 578 | sub.timeout = TIPC_WAIT_FOREVER; |
|---|
| 577 | 579 | sub.filter = filter; |
|---|
| 578 | | - *(u32 *)&sub.usr_handle = port; |
|---|
| 580 | + *(u64 *)&sub.usr_handle = (u64)port; |
|---|
| 579 | 581 | |
|---|
| 580 | | - con = tipc_conn_alloc(tipc_topsrv(net)); |
|---|
| 582 | + con = tipc_conn_alloc(tipc_topsrv(net), NULL); |
|---|
| 581 | 583 | if (IS_ERR(con)) |
|---|
| 582 | 584 | return false; |
|---|
| 583 | 585 | |
|---|
| 584 | 586 | *conid = con->conid; |
|---|
| 585 | | - con->sock = NULL; |
|---|
| 586 | 587 | rc = tipc_conn_rcv_sub(tipc_topsrv(net), con, &sub); |
|---|
| 587 | | - if (rc >= 0) |
|---|
| 588 | | - return true; |
|---|
| 588 | + if (rc) |
|---|
| 589 | + conn_put(con); |
|---|
| 590 | + |
|---|
| 589 | 591 | conn_put(con); |
|---|
| 590 | | - return false; |
|---|
| 592 | + return !rc; |
|---|
| 591 | 593 | } |
|---|
| 592 | 594 | |
|---|
| 593 | 595 | void tipc_topsrv_kern_unsubscr(struct net *net, int conid) |
|---|
| .. | .. |
|---|
| 619 | 621 | memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); |
|---|
| 620 | 622 | skb_queue_head_init(&evtq); |
|---|
| 621 | 623 | __skb_queue_tail(&evtq, skb); |
|---|
| 624 | + tipc_loopback_trace(net, &evtq); |
|---|
| 622 | 625 | tipc_sk_rcv(net, &evtq); |
|---|
| 623 | 626 | } |
|---|
| 624 | 627 | |
|---|
| .. | .. |
|---|
| 658 | 661 | return -ENOMEM; |
|---|
| 659 | 662 | |
|---|
| 660 | 663 | srv->net = net; |
|---|
| 661 | | - srv->max_rcvbuf_size = sizeof(struct tipc_subscr); |
|---|
| 662 | 664 | INIT_WORK(&srv->awork, tipc_topsrv_accept); |
|---|
| 663 | 665 | |
|---|
| 664 | 666 | strscpy(srv->name, name, sizeof(srv->name)); |
|---|
| .. | .. |
|---|
| 706 | 708 | __module_get(lsock->sk->sk_prot_creator->owner); |
|---|
| 707 | 709 | srv->listener = NULL; |
|---|
| 708 | 710 | spin_unlock_bh(&srv->idr_lock); |
|---|
| 709 | | - sock_release(lsock); |
|---|
| 711 | + |
|---|
| 710 | 712 | tipc_topsrv_work_stop(srv); |
|---|
| 713 | + sock_release(lsock); |
|---|
| 711 | 714 | idr_destroy(&srv->conn_idr); |
|---|
| 712 | 715 | kfree(srv); |
|---|
| 713 | 716 | } |
|---|