aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/core.h5
-rw-r--r--net/tipc/msg.h1
-rw-r--r--net/tipc/server.c121
-rw-r--r--net/tipc/server.h5
-rw-r--r--net/tipc/socket.c32
5 files changed, 124 insertions, 40 deletions
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 5cc5398be722..964342689f2c 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -132,6 +132,11 @@ static inline struct list_head *tipc_nodes(struct net *net)
132 return &tipc_net(net)->node_list; 132 return &tipc_net(net)->node_list;
133} 133}
134 134
135static inline struct tipc_server *tipc_topsrv(struct net *net)
136{
137 return tipc_net(net)->topsrv;
138}
139
135static inline unsigned int tipc_hashfn(u32 addr) 140static inline unsigned int tipc_hashfn(u32 addr)
136{ 141{
137 return addr & (NODE_HTABLE_SIZE - 1); 142 return addr & (NODE_HTABLE_SIZE - 1);
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index c843fd2bc48d..d058b1c464e9 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -78,6 +78,7 @@ struct plist;
78#define MSG_FRAGMENTER 12 78#define MSG_FRAGMENTER 12
79#define LINK_CONFIG 13 79#define LINK_CONFIG 13
80#define SOCK_WAKEUP 14 /* pseudo user */ 80#define SOCK_WAKEUP 14 /* pseudo user */
81#define TOP_SRV 15 /* pseudo user */
81 82
82/* 83/*
83 * Message header sizes 84 * Message header sizes
diff --git a/net/tipc/server.c b/net/tipc/server.c
index 3cd6402e812c..713077536d0c 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -36,6 +36,8 @@
36#include "server.h" 36#include "server.h"
37#include "core.h" 37#include "core.h"
38#include "socket.h" 38#include "socket.h"
39#include "addr.h"
40#include "msg.h"
39#include <net/sock.h> 41#include <net/sock.h>
40#include <linux/module.h> 42#include <linux/module.h>
41 43
@@ -105,13 +107,11 @@ static void tipc_conn_kref_release(struct kref *kref)
105 kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); 107 kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr));
106 sock_release(sock); 108 sock_release(sock);
107 con->sock = NULL; 109 con->sock = NULL;
108
109 spin_lock_bh(&s->idr_lock);
110 idr_remove(&s->conn_idr, con->conid);
111 s->idr_in_use--;
112 spin_unlock_bh(&s->idr_lock);
113 } 110 }
114 111 spin_lock_bh(&s->idr_lock);
112 idr_remove(&s->conn_idr, con->conid);
113 s->idr_in_use--;
114 spin_unlock_bh(&s->idr_lock);
115 tipc_clean_outqueues(con); 115 tipc_clean_outqueues(con);
116 kfree(con); 116 kfree(con);
117} 117}
@@ -197,7 +197,8 @@ static void tipc_close_conn(struct tipc_conn *con)
197 struct tipc_server *s = con->server; 197 struct tipc_server *s = con->server;
198 198
199 if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { 199 if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
200 tipc_unregister_callbacks(con); 200 if (con->sock)
201 tipc_unregister_callbacks(con);
201 202
202 if (con->conid) 203 if (con->conid)
203 s->tipc_conn_release(con->conid, con->usr_data); 204 s->tipc_conn_release(con->conid, con->usr_data);
@@ -207,8 +208,8 @@ static void tipc_close_conn(struct tipc_conn *con)
207 * are harmless for us here as we have already deleted this 208 * are harmless for us here as we have already deleted this
208 * connection from server connection list. 209 * connection from server connection list.
209 */ 210 */
210 kernel_sock_shutdown(con->sock, SHUT_RDWR); 211 if (con->sock)
211 212 kernel_sock_shutdown(con->sock, SHUT_RDWR);
212 conn_put(con); 213 conn_put(con);
213 } 214 }
214} 215}
@@ -487,38 +488,104 @@ void tipc_conn_terminate(struct tipc_server *s, int conid)
487 } 488 }
488} 489}
489 490
491bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
492 u32 lower, u32 upper, int *conid)
493{
494 struct tipc_subscriber *scbr;
495 struct tipc_subscr sub;
496 struct tipc_server *s;
497 struct tipc_conn *con;
498
499 sub.seq.type = type;
500 sub.seq.lower = lower;
501 sub.seq.upper = upper;
502 sub.timeout = TIPC_WAIT_FOREVER;
503 sub.filter = TIPC_SUB_PORTS;
504 *(u32 *)&sub.usr_handle = port;
505
506 con = tipc_alloc_conn(tipc_topsrv(net));
507 if (!con)
508 return false;
509
510 *conid = con->conid;
511 s = con->server;
512 scbr = s->tipc_conn_new(*conid);
513 if (!scbr) {
514 tipc_close_conn(con);
515 return false;
516 }
517
518 con->usr_data = scbr;
519 con->sock = NULL;
520 s->tipc_conn_recvmsg(net, *conid, NULL, scbr, &sub, sizeof(sub));
521 return true;
522}
523
524void tipc_topsrv_kern_unsubscr(struct net *net, int conid)
525{
526 struct tipc_conn *con;
527
528 con = tipc_conn_lookup(tipc_topsrv(net), conid);
529 if (!con)
530 return;
531 tipc_close_conn(con);
532 conn_put(con);
533}
534
535static void tipc_send_kern_top_evt(struct net *net, struct tipc_event *evt)
536{
537 u32 port = *(u32 *)&evt->s.usr_handle;
538 u32 self = tipc_own_addr(net);
539 struct sk_buff_head evtq;
540 struct sk_buff *skb;
541
542 skb = tipc_msg_create(TOP_SRV, 0, INT_H_SIZE, sizeof(*evt),
543 self, self, port, port, 0);
544 if (!skb)
545 return;
546 msg_set_dest_droppable(buf_msg(skb), true);
547 memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt));
548 skb_queue_head_init(&evtq);
549 __skb_queue_tail(&evtq, skb);
550 tipc_sk_rcv(net, &evtq);
551}
552
490static void tipc_send_to_sock(struct tipc_conn *con) 553static void tipc_send_to_sock(struct tipc_conn *con)
491{ 554{
492 int count = 0;
493 struct tipc_server *s = con->server; 555 struct tipc_server *s = con->server;
494 struct outqueue_entry *e; 556 struct outqueue_entry *e;
557 struct tipc_event *evt;
495 struct msghdr msg; 558 struct msghdr msg;
559 int count = 0;
496 int ret; 560 int ret;
497 561
498 spin_lock_bh(&con->outqueue_lock); 562 spin_lock_bh(&con->outqueue_lock);
499 while (test_bit(CF_CONNECTED, &con->flags)) { 563 while (test_bit(CF_CONNECTED, &con->flags)) {
500 e = list_entry(con->outqueue.next, struct outqueue_entry, 564 e = list_entry(con->outqueue.next, struct outqueue_entry, list);
501 list);
502 if ((struct list_head *) e == &con->outqueue) 565 if ((struct list_head *) e == &con->outqueue)
503 break; 566 break;
504 spin_unlock_bh(&con->outqueue_lock);
505 567
506 memset(&msg, 0, sizeof(msg)); 568 spin_unlock_bh(&con->outqueue_lock);
507 msg.msg_flags = MSG_DONTWAIT;
508 569
509 if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) { 570 if (con->sock) {
510 msg.msg_name = &e->dest; 571 memset(&msg, 0, sizeof(msg));
511 msg.msg_namelen = sizeof(struct sockaddr_tipc); 572 msg.msg_flags = MSG_DONTWAIT;
512 } 573 if (s->type == SOCK_DGRAM || s->type == SOCK_RDM) {
513 ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1, 574 msg.msg_name = &e->dest;
514 e->iov.iov_len); 575 msg.msg_namelen = sizeof(struct sockaddr_tipc);
515 if (ret == -EWOULDBLOCK || ret == 0) { 576 }
516 cond_resched(); 577 ret = kernel_sendmsg(con->sock, &msg, &e->iov, 1,
517 goto out; 578 e->iov.iov_len);
518 } else if (ret < 0) { 579 if (ret == -EWOULDBLOCK || ret == 0) {
519 goto send_err; 580 cond_resched();
581 goto out;
582 } else if (ret < 0) {
583 goto send_err;
584 }
585 } else {
586 evt = e->iov.iov_base;
587 tipc_send_kern_top_evt(s->net, evt);
520 } 588 }
521
522 /* Don't starve users filling buffers */ 589 /* Don't starve users filling buffers */
523 if (++count >= MAX_SEND_MSG_COUNT) { 590 if (++count >= MAX_SEND_MSG_COUNT) {
524 cond_resched(); 591 cond_resched();
diff --git a/net/tipc/server.h b/net/tipc/server.h
index 34f8055afa3b..2113c9192633 100644
--- a/net/tipc/server.h
+++ b/net/tipc/server.h
@@ -83,13 +83,16 @@ struct tipc_server {
83int tipc_conn_sendmsg(struct tipc_server *s, int conid, 83int tipc_conn_sendmsg(struct tipc_server *s, int conid,
84 struct sockaddr_tipc *addr, void *data, size_t len); 84 struct sockaddr_tipc *addr, void *data, size_t len);
85 85
86bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,
87 u32 lower, u32 upper, int *conid);
88void tipc_topsrv_kern_unsubscr(struct net *net, int conid);
89
86/** 90/**
87 * tipc_conn_terminate - terminate connection with server 91 * tipc_conn_terminate - terminate connection with server
88 * 92 *
89 * Note: Must call it in process context since it might sleep 93 * Note: Must call it in process context since it might sleep
90 */ 94 */
91void tipc_conn_terminate(struct tipc_server *s, int conid); 95void tipc_conn_terminate(struct tipc_server *s, int conid);
92
93int tipc_server_start(struct tipc_server *s); 96int tipc_server_start(struct tipc_server *s);
94 97
95void tipc_server_stop(struct tipc_server *s); 98void tipc_server_stop(struct tipc_server *s);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index d50edd6e0019..9a7e7b5cf23f 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -896,6 +896,10 @@ exit:
896 kfree_skb(skb); 896 kfree_skb(skb);
897} 897}
898 898
899static void tipc_sk_top_evt(struct tipc_sock *tsk, struct tipc_event *evt)
900{
901}
902
899/** 903/**
900 * tipc_sendmsg - send message in connectionless manner 904 * tipc_sendmsg - send message in connectionless manner
901 * @sock: socket structure 905 * @sock: socket structure
@@ -1671,20 +1675,24 @@ static bool filter_rcv(struct sock *sk, struct sk_buff *skb,
1671 struct tipc_msg *hdr = buf_msg(skb); 1675 struct tipc_msg *hdr = buf_msg(skb);
1672 unsigned int limit = rcvbuf_limit(sk, skb); 1676 unsigned int limit = rcvbuf_limit(sk, skb);
1673 int err = TIPC_OK; 1677 int err = TIPC_OK;
1674 int usr = msg_user(hdr);
1675 u32 onode;
1676
1677 if (unlikely(msg_user(hdr) == CONN_MANAGER)) {
1678 tipc_sk_proto_rcv(tsk, skb, xmitq);
1679 return false;
1680 }
1681 1678
1682 if (unlikely(usr == SOCK_WAKEUP)) { 1679 if (unlikely(!msg_isdata(hdr))) {
1683 onode = msg_orignode(hdr); 1680 switch (msg_user(hdr)) {
1681 case CONN_MANAGER:
1682 tipc_sk_proto_rcv(tsk, skb, xmitq);
1683 return false;
1684 case SOCK_WAKEUP:
1685 u32_del(&tsk->cong_links, msg_orignode(hdr));
1686 tsk->cong_link_cnt--;
1687 sk->sk_write_space(sk);
1688 break;
1689 case TOP_SRV:
1690 tipc_sk_top_evt(tsk, (void *)msg_data(hdr));
1691 break;
1692 default:
1693 break;
1694 }
1684 kfree_skb(skb); 1695 kfree_skb(skb);
1685 u32_del(&tsk->cong_links, onode);
1686 tsk->cong_link_cnt--;
1687 sk->sk_write_space(sk);
1688 return false; 1696 return false;
1689 } 1697 }
1690 1698