0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include "core.h"
0039 #include "name_table.h"
0040 #include "subscr.h"
0041
0042 static void tipc_sub_send_event(struct tipc_subscription *sub,
0043 struct publication *p,
0044 u32 event)
0045 {
0046 struct tipc_subscr *s = &sub->evt.s;
0047 struct tipc_event *evt = &sub->evt;
0048
0049 if (sub->inactive)
0050 return;
0051 tipc_evt_write(evt, event, event);
0052 if (p) {
0053 tipc_evt_write(evt, found_lower, p->sr.lower);
0054 tipc_evt_write(evt, found_upper, p->sr.upper);
0055 tipc_evt_write(evt, port.ref, p->sk.ref);
0056 tipc_evt_write(evt, port.node, p->sk.node);
0057 } else {
0058 tipc_evt_write(evt, found_lower, s->seq.lower);
0059 tipc_evt_write(evt, found_upper, s->seq.upper);
0060 tipc_evt_write(evt, port.ref, 0);
0061 tipc_evt_write(evt, port.node, 0);
0062 }
0063 tipc_topsrv_queue_evt(sub->net, sub->conid, event, evt);
0064 }
0065
0066
0067
0068
0069
0070
0071
0072
0073 static bool tipc_sub_check_overlap(struct tipc_service_range *subscribed,
0074 struct tipc_service_range *found)
0075 {
0076 u32 found_lower = found->lower;
0077 u32 found_upper = found->upper;
0078
0079 if (found_lower < subscribed->lower)
0080 found_lower = subscribed->lower;
0081 if (found_upper > subscribed->upper)
0082 found_upper = subscribed->upper;
0083 return found_lower <= found_upper;
0084 }
0085
0086 void tipc_sub_report_overlap(struct tipc_subscription *sub,
0087 struct publication *p,
0088 u32 event, bool must)
0089 {
0090 struct tipc_service_range *sr = &sub->s.seq;
0091 u32 filter = sub->s.filter;
0092
0093 if (!tipc_sub_check_overlap(sr, &p->sr))
0094 return;
0095 if (!must && !(filter & TIPC_SUB_PORTS))
0096 return;
0097 if (filter & TIPC_SUB_CLUSTER_SCOPE && p->scope == TIPC_NODE_SCOPE)
0098 return;
0099 if (filter & TIPC_SUB_NODE_SCOPE && p->scope != TIPC_NODE_SCOPE)
0100 return;
0101 spin_lock(&sub->lock);
0102 tipc_sub_send_event(sub, p, event);
0103 spin_unlock(&sub->lock);
0104 }
0105
0106 static void tipc_sub_timeout(struct timer_list *t)
0107 {
0108 struct tipc_subscription *sub = from_timer(sub, t, timer);
0109
0110 spin_lock(&sub->lock);
0111 tipc_sub_send_event(sub, NULL, TIPC_SUBSCR_TIMEOUT);
0112 sub->inactive = true;
0113 spin_unlock(&sub->lock);
0114 }
0115
0116 static void tipc_sub_kref_release(struct kref *kref)
0117 {
0118 kfree(container_of(kref, struct tipc_subscription, kref));
0119 }
0120
0121 void tipc_sub_put(struct tipc_subscription *subscription)
0122 {
0123 kref_put(&subscription->kref, tipc_sub_kref_release);
0124 }
0125
0126 void tipc_sub_get(struct tipc_subscription *subscription)
0127 {
0128 kref_get(&subscription->kref);
0129 }
0130
0131 struct tipc_subscription *tipc_sub_subscribe(struct net *net,
0132 struct tipc_subscr *s,
0133 int conid)
0134 {
0135 u32 lower = tipc_sub_read(s, seq.lower);
0136 u32 upper = tipc_sub_read(s, seq.upper);
0137 u32 filter = tipc_sub_read(s, filter);
0138 struct tipc_subscription *sub;
0139 u32 timeout;
0140
0141 if ((filter & TIPC_SUB_PORTS && filter & TIPC_SUB_SERVICE) ||
0142 lower > upper) {
0143 pr_warn("Subscription rejected, illegal request\n");
0144 return NULL;
0145 }
0146 sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
0147 if (!sub) {
0148 pr_warn("Subscription rejected, no memory\n");
0149 return NULL;
0150 }
0151 INIT_LIST_HEAD(&sub->service_list);
0152 INIT_LIST_HEAD(&sub->sub_list);
0153 sub->net = net;
0154 sub->conid = conid;
0155 sub->inactive = false;
0156 memcpy(&sub->evt.s, s, sizeof(*s));
0157 sub->s.seq.type = tipc_sub_read(s, seq.type);
0158 sub->s.seq.lower = lower;
0159 sub->s.seq.upper = upper;
0160 sub->s.filter = filter;
0161 sub->s.timeout = tipc_sub_read(s, timeout);
0162 memcpy(sub->s.usr_handle, s->usr_handle, 8);
0163 spin_lock_init(&sub->lock);
0164 kref_init(&sub->kref);
0165 if (!tipc_nametbl_subscribe(sub)) {
0166 kfree(sub);
0167 return NULL;
0168 }
0169 timer_setup(&sub->timer, tipc_sub_timeout, 0);
0170 timeout = tipc_sub_read(&sub->evt.s, timeout);
0171 if (timeout != TIPC_WAIT_FOREVER)
0172 mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout));
0173 return sub;
0174 }
0175
0176 void tipc_sub_unsubscribe(struct tipc_subscription *sub)
0177 {
0178 tipc_nametbl_unsubscribe(sub);
0179 if (sub->evt.s.timeout != TIPC_WAIT_FOREVER)
0180 del_timer_sync(&sub->timer);
0181 list_del(&sub->sub_list);
0182 tipc_sub_put(sub);
0183 }