diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bcast.c | 5 | ||||
-rw-r--r-- | net/tipc/bcast.h | 1 | ||||
-rw-r--r-- | net/tipc/bearer.c | 18 | ||||
-rw-r--r-- | net/tipc/link.c | 167 | ||||
-rw-r--r-- | net/tipc/link.h | 7 | ||||
-rw-r--r-- | net/tipc/name_table.c | 20 | ||||
-rw-r--r-- | net/tipc/net.c | 7 | ||||
-rw-r--r-- | net/tipc/netlink.c | 69 | ||||
-rw-r--r-- | net/tipc/netlink.h | 11 | ||||
-rw-r--r-- | net/tipc/netlink_compat.c | 2 | ||||
-rw-r--r-- | net/tipc/node.c | 130 | ||||
-rw-r--r-- | net/tipc/server.c | 4 | ||||
-rw-r--r-- | net/tipc/socket.c | 9 | ||||
-rw-r--r-- | net/tipc/subscr.c | 132 | ||||
-rw-r--r-- | net/tipc/subscr.h | 11 | ||||
-rw-r--r-- | net/tipc/udp_media.c | 44 |
16 files changed, 331 insertions, 306 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index e401108360a2..ae469b37d852 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -412,11 +412,6 @@ enomem: | |||
412 | return -ENOMEM; | 412 | return -ENOMEM; |
413 | } | 413 | } |
414 | 414 | ||
415 | void tipc_bcast_reinit(struct net *net) | ||
416 | { | ||
417 | tipc_link_reinit(tipc_bc_sndlink(net), tipc_own_addr(net)); | ||
418 | } | ||
419 | |||
420 | void tipc_bcast_stop(struct net *net) | 415 | void tipc_bcast_stop(struct net *net) |
421 | { | 416 | { |
422 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 417 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 1944c6c00bb9..d5e79b3767fd 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -46,7 +46,6 @@ struct tipc_node_map; | |||
46 | extern const char tipc_bclink_name[]; | 46 | extern const char tipc_bclink_name[]; |
47 | 47 | ||
48 | int tipc_bcast_init(struct net *net); | 48 | int tipc_bcast_init(struct net *net); |
49 | void tipc_bcast_reinit(struct net *net); | ||
50 | void tipc_bcast_stop(struct net *net); | 49 | void tipc_bcast_stop(struct net *net); |
51 | void tipc_bcast_add_peer(struct net *net, struct tipc_link *l, | 50 | void tipc_bcast_add_peer(struct net *net, struct tipc_link *l, |
52 | struct sk_buff_head *xmitq); | 51 | struct sk_buff_head *xmitq); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 802ffad3200d..27a5406213c6 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "link.h" | 40 | #include "link.h" |
41 | #include "discover.h" | 41 | #include "discover.h" |
42 | #include "bcast.h" | 42 | #include "bcast.h" |
43 | #include "netlink.h" | ||
43 | 44 | ||
44 | #define MAX_ADDR_STR 60 | 45 | #define MAX_ADDR_STR 60 |
45 | 46 | ||
@@ -54,23 +55,6 @@ static struct tipc_media * const media_info_array[] = { | |||
54 | NULL | 55 | NULL |
55 | }; | 56 | }; |
56 | 57 | ||
57 | static const struct nla_policy | ||
58 | tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1] = { | ||
59 | [TIPC_NLA_BEARER_UNSPEC] = { .type = NLA_UNSPEC }, | ||
60 | [TIPC_NLA_BEARER_NAME] = { | ||
61 | .type = NLA_STRING, | ||
62 | .len = TIPC_MAX_BEARER_NAME | ||
63 | }, | ||
64 | [TIPC_NLA_BEARER_PROP] = { .type = NLA_NESTED }, | ||
65 | [TIPC_NLA_BEARER_DOMAIN] = { .type = NLA_U32 } | ||
66 | }; | ||
67 | |||
68 | static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { | ||
69 | [TIPC_NLA_MEDIA_UNSPEC] = { .type = NLA_UNSPEC }, | ||
70 | [TIPC_NLA_MEDIA_NAME] = { .type = NLA_STRING }, | ||
71 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } | ||
72 | }; | ||
73 | |||
74 | static void bearer_disable(struct net *net, struct tipc_bearer *b); | 58 | static void bearer_disable(struct net *net, struct tipc_bearer *b); |
75 | 59 | ||
76 | /** | 60 | /** |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 347cdc99ed09..7d2bb3e70baa 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/link.c: TIPC link code | 2 | * net/tipc/link.c: TIPC link code |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2007, 2012-2015, Ericsson AB | 4 | * Copyright (c) 1996-2007, 2012-2016, Ericsson AB |
5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -123,11 +123,11 @@ struct tipc_stats { | |||
123 | struct tipc_link { | 123 | struct tipc_link { |
124 | u32 addr; | 124 | u32 addr; |
125 | char name[TIPC_MAX_LINK_NAME]; | 125 | char name[TIPC_MAX_LINK_NAME]; |
126 | struct tipc_media_addr *media_addr; | ||
127 | struct net *net; | 126 | struct net *net; |
128 | 127 | ||
129 | /* Management and link supervision data */ | 128 | /* Management and link supervision data */ |
130 | u32 peer_session; | 129 | u32 peer_session; |
130 | u32 session; | ||
131 | u32 peer_bearer_id; | 131 | u32 peer_bearer_id; |
132 | u32 bearer_id; | 132 | u32 bearer_id; |
133 | u32 tolerance; | 133 | u32 tolerance; |
@@ -137,11 +137,7 @@ struct tipc_link { | |||
137 | u16 peer_caps; | 137 | u16 peer_caps; |
138 | bool active; | 138 | bool active; |
139 | u32 silent_intv_cnt; | 139 | u32 silent_intv_cnt; |
140 | struct { | 140 | char if_name[TIPC_MAX_IF_NAME]; |
141 | unchar hdr[INT_H_SIZE]; | ||
142 | unchar body[TIPC_MAX_IF_NAME]; | ||
143 | } proto_msg; | ||
144 | struct tipc_msg *pmsg; | ||
145 | u32 priority; | 141 | u32 priority; |
146 | char net_plane; | 142 | char net_plane; |
147 | 143 | ||
@@ -196,14 +192,6 @@ struct tipc_link { | |||
196 | static const char *link_co_err = "Link tunneling error, "; | 192 | static const char *link_co_err = "Link tunneling error, "; |
197 | static const char *link_rst_msg = "Resetting link "; | 193 | static const char *link_rst_msg = "Resetting link "; |
198 | 194 | ||
199 | /* Properties valid for media, bearar and link */ | ||
200 | static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | ||
201 | [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, | ||
202 | [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, | ||
203 | [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, | ||
204 | [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 } | ||
205 | }; | ||
206 | |||
207 | /* Send states for broadcast NACKs | 195 | /* Send states for broadcast NACKs |
208 | */ | 196 | */ |
209 | enum { | 197 | enum { |
@@ -216,10 +204,11 @@ enum { | |||
216 | * Interval between NACKs when packets arrive out of order | 204 | * Interval between NACKs when packets arrive out of order |
217 | */ | 205 | */ |
218 | #define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2) | 206 | #define TIPC_NACK_INTV (TIPC_MIN_LINK_WIN * 2) |
219 | /* | 207 | |
220 | * Out-of-range value for link session numbers | 208 | /* Wildcard value for link session numbers. When it is known that |
209 | * peer endpoint is down, any session number must be accepted. | ||
221 | */ | 210 | */ |
222 | #define WILDCARD_SESSION 0x10000 | 211 | #define ANY_SESSION 0x10000 |
223 | 212 | ||
224 | /* Link FSM states: | 213 | /* Link FSM states: |
225 | */ | 214 | */ |
@@ -399,16 +388,6 @@ char *tipc_link_name(struct tipc_link *l) | |||
399 | return l->name; | 388 | return l->name; |
400 | } | 389 | } |
401 | 390 | ||
402 | static u32 link_own_addr(struct tipc_link *l) | ||
403 | { | ||
404 | return msg_prevnode(l->pmsg); | ||
405 | } | ||
406 | |||
407 | void tipc_link_reinit(struct tipc_link *l, u32 addr) | ||
408 | { | ||
409 | msg_set_prevnode(l->pmsg, addr); | ||
410 | } | ||
411 | |||
412 | /** | 391 | /** |
413 | * tipc_link_create - create a new link | 392 | * tipc_link_create - create a new link |
414 | * @n: pointer to associated node | 393 | * @n: pointer to associated node |
@@ -442,29 +421,22 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id, | |||
442 | struct tipc_link **link) | 421 | struct tipc_link **link) |
443 | { | 422 | { |
444 | struct tipc_link *l; | 423 | struct tipc_link *l; |
445 | struct tipc_msg *hdr; | ||
446 | 424 | ||
447 | l = kzalloc(sizeof(*l), GFP_ATOMIC); | 425 | l = kzalloc(sizeof(*l), GFP_ATOMIC); |
448 | if (!l) | 426 | if (!l) |
449 | return false; | 427 | return false; |
450 | *link = l; | 428 | *link = l; |
451 | l->pmsg = (struct tipc_msg *)&l->proto_msg; | 429 | l->session = session; |
452 | hdr = l->pmsg; | ||
453 | tipc_msg_init(ownnode, hdr, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, peer); | ||
454 | msg_set_size(hdr, sizeof(l->proto_msg)); | ||
455 | msg_set_session(hdr, session); | ||
456 | msg_set_bearer_id(hdr, l->bearer_id); | ||
457 | 430 | ||
458 | /* Note: peer i/f name is completed by reset/activate message */ | 431 | /* Note: peer i/f name is completed by reset/activate message */ |
459 | sprintf(l->name, "%u.%u.%u:%s-%u.%u.%u:unknown", | 432 | sprintf(l->name, "%u.%u.%u:%s-%u.%u.%u:unknown", |
460 | tipc_zone(ownnode), tipc_cluster(ownnode), tipc_node(ownnode), | 433 | tipc_zone(ownnode), tipc_cluster(ownnode), tipc_node(ownnode), |
461 | if_name, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); | 434 | if_name, tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); |
462 | strcpy((char *)msg_data(hdr), if_name); | 435 | strcpy(l->if_name, if_name); |
463 | |||
464 | l->addr = peer; | 436 | l->addr = peer; |
465 | l->peer_caps = peer_caps; | 437 | l->peer_caps = peer_caps; |
466 | l->net = net; | 438 | l->net = net; |
467 | l->peer_session = WILDCARD_SESSION; | 439 | l->peer_session = ANY_SESSION; |
468 | l->bearer_id = bearer_id; | 440 | l->bearer_id = bearer_id; |
469 | l->tolerance = tolerance; | 441 | l->tolerance = tolerance; |
470 | l->net_plane = net_plane; | 442 | l->net_plane = net_plane; |
@@ -791,7 +763,7 @@ static int link_schedule_user(struct tipc_link *link, struct sk_buff_head *list) | |||
791 | struct tipc_msg *msg = buf_msg(skb_peek(list)); | 763 | struct tipc_msg *msg = buf_msg(skb_peek(list)); |
792 | int imp = msg_importance(msg); | 764 | int imp = msg_importance(msg); |
793 | u32 oport = msg_origport(msg); | 765 | u32 oport = msg_origport(msg); |
794 | u32 addr = link_own_addr(link); | 766 | u32 addr = tipc_own_addr(link->net); |
795 | struct sk_buff *skb; | 767 | struct sk_buff *skb; |
796 | 768 | ||
797 | /* This really cannot happen... */ | 769 | /* This really cannot happen... */ |
@@ -840,16 +812,9 @@ void link_prepare_wakeup(struct tipc_link *l) | |||
840 | 812 | ||
841 | void tipc_link_reset(struct tipc_link *l) | 813 | void tipc_link_reset(struct tipc_link *l) |
842 | { | 814 | { |
843 | /* Link is down, accept any session */ | 815 | l->peer_session = ANY_SESSION; |
844 | l->peer_session = WILDCARD_SESSION; | 816 | l->session++; |
845 | |||
846 | /* If peer is up, it only accepts an incremented session number */ | ||
847 | msg_set_session(l->pmsg, msg_session(l->pmsg) + 1); | ||
848 | |||
849 | /* Prepare for renewed mtu size negotiation */ | ||
850 | l->mtu = l->advertised_mtu; | 817 | l->mtu = l->advertised_mtu; |
851 | |||
852 | /* Clean up all queues and counters: */ | ||
853 | __skb_queue_purge(&l->transmq); | 818 | __skb_queue_purge(&l->transmq); |
854 | __skb_queue_purge(&l->deferdq); | 819 | __skb_queue_purge(&l->deferdq); |
855 | skb_queue_splice_init(&l->wakeupq, l->inputq); | 820 | skb_queue_splice_init(&l->wakeupq, l->inputq); |
@@ -904,8 +869,10 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, | |||
904 | if (unlikely(l->backlog[i].len >= l->backlog[i].limit)) | 869 | if (unlikely(l->backlog[i].len >= l->backlog[i].limit)) |
905 | return link_schedule_user(l, list); | 870 | return link_schedule_user(l, list); |
906 | } | 871 | } |
907 | if (unlikely(msg_size(hdr) > mtu)) | 872 | if (unlikely(msg_size(hdr) > mtu)) { |
873 | skb_queue_purge(list); | ||
908 | return -EMSGSIZE; | 874 | return -EMSGSIZE; |
875 | } | ||
909 | 876 | ||
910 | /* Prepare each packet for sending, and add to relevant queue: */ | 877 | /* Prepare each packet for sending, and add to relevant queue: */ |
911 | while (skb_queue_len(list)) { | 878 | while (skb_queue_len(list)) { |
@@ -917,8 +884,10 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, | |||
917 | 884 | ||
918 | if (likely(skb_queue_len(transmq) < maxwin)) { | 885 | if (likely(skb_queue_len(transmq) < maxwin)) { |
919 | _skb = skb_clone(skb, GFP_ATOMIC); | 886 | _skb = skb_clone(skb, GFP_ATOMIC); |
920 | if (!_skb) | 887 | if (!_skb) { |
888 | skb_queue_purge(list); | ||
921 | return -ENOBUFS; | 889 | return -ENOBUFS; |
890 | } | ||
922 | __skb_dequeue(list); | 891 | __skb_dequeue(list); |
923 | __skb_queue_tail(transmq, skb); | 892 | __skb_queue_tail(transmq, skb); |
924 | __skb_queue_tail(xmitq, _skb); | 893 | __skb_queue_tail(xmitq, _skb); |
@@ -1153,7 +1122,7 @@ int tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq) | |||
1153 | 1122 | ||
1154 | /* Broadcast ACK must be sent via a unicast link => defer to caller */ | 1123 | /* Broadcast ACK must be sent via a unicast link => defer to caller */ |
1155 | if (link_is_bc_rcvlink(l)) { | 1124 | if (link_is_bc_rcvlink(l)) { |
1156 | if (((l->rcv_nxt ^ link_own_addr(l)) & 0xf) != 0xf) | 1125 | if (((l->rcv_nxt ^ tipc_own_addr(l->net)) & 0xf) != 0xf) |
1157 | return 0; | 1126 | return 0; |
1158 | l->rcv_unacked = 0; | 1127 | l->rcv_unacked = 0; |
1159 | return TIPC_LINK_SND_BC_ACK; | 1128 | return TIPC_LINK_SND_BC_ACK; |
@@ -1261,39 +1230,34 @@ drop: | |||
1261 | return rc; | 1230 | return rc; |
1262 | } | 1231 | } |
1263 | 1232 | ||
1264 | /* | ||
1265 | * Send protocol message to the other endpoint. | ||
1266 | */ | ||
1267 | static void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, | ||
1268 | int probe_msg, u32 gap, u32 tolerance, | ||
1269 | u32 priority) | ||
1270 | { | ||
1271 | struct sk_buff *skb = NULL; | ||
1272 | struct sk_buff_head xmitq; | ||
1273 | |||
1274 | __skb_queue_head_init(&xmitq); | ||
1275 | tipc_link_build_proto_msg(l, msg_typ, probe_msg, gap, | ||
1276 | tolerance, priority, &xmitq); | ||
1277 | skb = __skb_dequeue(&xmitq); | ||
1278 | if (!skb) | ||
1279 | return; | ||
1280 | tipc_bearer_xmit_skb(l->net, l->bearer_id, skb, l->media_addr); | ||
1281 | l->rcv_unacked = 0; | ||
1282 | } | ||
1283 | |||
1284 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | 1233 | static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, |
1285 | u16 rcvgap, int tolerance, int priority, | 1234 | u16 rcvgap, int tolerance, int priority, |
1286 | struct sk_buff_head *xmitq) | 1235 | struct sk_buff_head *xmitq) |
1287 | { | 1236 | { |
1288 | struct sk_buff *skb = NULL; | 1237 | struct sk_buff *skb; |
1289 | struct tipc_msg *hdr = l->pmsg; | 1238 | struct tipc_msg *hdr; |
1239 | struct sk_buff_head *dfq = &l->deferdq; | ||
1290 | bool node_up = link_is_up(l->bc_rcvlink); | 1240 | bool node_up = link_is_up(l->bc_rcvlink); |
1291 | 1241 | ||
1292 | /* Don't send protocol message during reset or link failover */ | 1242 | /* Don't send protocol message during reset or link failover */ |
1293 | if (tipc_link_is_blocked(l)) | 1243 | if (tipc_link_is_blocked(l)) |
1294 | return; | 1244 | return; |
1295 | 1245 | ||
1296 | msg_set_type(hdr, mtyp); | 1246 | if (!tipc_link_is_up(l) && (mtyp == STATE_MSG)) |
1247 | return; | ||
1248 | |||
1249 | if (!skb_queue_empty(dfq)) | ||
1250 | rcvgap = buf_seqno(skb_peek(dfq)) - l->rcv_nxt; | ||
1251 | |||
1252 | skb = tipc_msg_create(LINK_PROTOCOL, mtyp, INT_H_SIZE, | ||
1253 | TIPC_MAX_IF_NAME, l->addr, | ||
1254 | tipc_own_addr(l->net), 0, 0, 0); | ||
1255 | if (!skb) | ||
1256 | return; | ||
1257 | |||
1258 | hdr = buf_msg(skb); | ||
1259 | msg_set_session(hdr, l->session); | ||
1260 | msg_set_bearer_id(hdr, l->bearer_id); | ||
1297 | msg_set_net_plane(hdr, l->net_plane); | 1261 | msg_set_net_plane(hdr, l->net_plane); |
1298 | msg_set_next_sent(hdr, l->snd_nxt); | 1262 | msg_set_next_sent(hdr, l->snd_nxt); |
1299 | msg_set_ack(hdr, l->rcv_nxt - 1); | 1263 | msg_set_ack(hdr, l->rcv_nxt - 1); |
@@ -1303,36 +1267,23 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, | |||
1303 | msg_set_linkprio(hdr, priority); | 1267 | msg_set_linkprio(hdr, priority); |
1304 | msg_set_redundant_link(hdr, node_up); | 1268 | msg_set_redundant_link(hdr, node_up); |
1305 | msg_set_seq_gap(hdr, 0); | 1269 | msg_set_seq_gap(hdr, 0); |
1306 | |||
1307 | /* Compatibility: created msg must not be in sequence with pkt flow */ | ||
1308 | msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2); | 1270 | msg_set_seqno(hdr, l->snd_nxt + U16_MAX / 2); |
1309 | 1271 | ||
1310 | if (mtyp == STATE_MSG) { | 1272 | if (mtyp == STATE_MSG) { |
1311 | if (!tipc_link_is_up(l)) | 1273 | msg_set_seq_gap(hdr, rcvgap); |
1312 | return; | 1274 | msg_set_size(hdr, INT_H_SIZE); |
1313 | |||
1314 | /* Override rcvgap if there are packets in deferred queue */ | ||
1315 | if (!skb_queue_empty(&l->deferdq)) | ||
1316 | rcvgap = buf_seqno(skb_peek(&l->deferdq)) - l->rcv_nxt; | ||
1317 | if (rcvgap) { | ||
1318 | msg_set_seq_gap(hdr, rcvgap); | ||
1319 | l->stats.sent_nacks++; | ||
1320 | } | ||
1321 | msg_set_probe(hdr, probe); | 1275 | msg_set_probe(hdr, probe); |
1322 | if (probe) | ||
1323 | l->stats.sent_probes++; | ||
1324 | l->stats.sent_states++; | 1276 | l->stats.sent_states++; |
1325 | l->rcv_unacked = 0; | 1277 | l->rcv_unacked = 0; |
1326 | } else { | 1278 | } else { |
1327 | /* RESET_MSG or ACTIVATE_MSG */ | 1279 | /* RESET_MSG or ACTIVATE_MSG */ |
1328 | msg_set_max_pkt(hdr, l->advertised_mtu); | 1280 | msg_set_max_pkt(hdr, l->advertised_mtu); |
1329 | msg_set_ack(hdr, l->rcv_nxt - 1); | 1281 | strcpy(msg_data(hdr), l->if_name); |
1330 | msg_set_next_sent(hdr, 1); | ||
1331 | } | 1282 | } |
1332 | skb = tipc_buf_acquire(msg_size(hdr)); | 1283 | if (probe) |
1333 | if (!skb) | 1284 | l->stats.sent_probes++; |
1334 | return; | 1285 | if (rcvgap) |
1335 | skb_copy_to_linear_data(skb, hdr, msg_size(hdr)); | 1286 | l->stats.sent_nacks++; |
1336 | skb->priority = TC_PRIO_CONTROL; | 1287 | skb->priority = TC_PRIO_CONTROL; |
1337 | __skb_queue_tail(xmitq, skb); | 1288 | __skb_queue_tail(xmitq, skb); |
1338 | } | 1289 | } |
@@ -1357,7 +1308,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | |||
1357 | 1308 | ||
1358 | /* At least one packet required for safe algorithm => add dummy */ | 1309 | /* At least one packet required for safe algorithm => add dummy */ |
1359 | skb = tipc_msg_create(TIPC_LOW_IMPORTANCE, TIPC_DIRECT_MSG, | 1310 | skb = tipc_msg_create(TIPC_LOW_IMPORTANCE, TIPC_DIRECT_MSG, |
1360 | BASIC_H_SIZE, 0, l->addr, link_own_addr(l), | 1311 | BASIC_H_SIZE, 0, l->addr, tipc_own_addr(l->net), |
1361 | 0, 0, TIPC_ERR_NO_PORT); | 1312 | 0, 0, TIPC_ERR_NO_PORT); |
1362 | if (!skb) { | 1313 | if (!skb) { |
1363 | pr_warn("%sunable to create tunnel packet\n", link_co_err); | 1314 | pr_warn("%sunable to create tunnel packet\n", link_co_err); |
@@ -1368,7 +1319,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | |||
1368 | __skb_queue_purge(&tmpxq); | 1319 | __skb_queue_purge(&tmpxq); |
1369 | 1320 | ||
1370 | /* Initialize reusable tunnel packet header */ | 1321 | /* Initialize reusable tunnel packet header */ |
1371 | tipc_msg_init(link_own_addr(l), &tnlhdr, TUNNEL_PROTOCOL, | 1322 | tipc_msg_init(tipc_own_addr(l->net), &tnlhdr, TUNNEL_PROTOCOL, |
1372 | mtyp, INT_H_SIZE, l->addr); | 1323 | mtyp, INT_H_SIZE, l->addr); |
1373 | pktcnt = skb_queue_len(&l->transmq) + skb_queue_len(&l->backlogq); | 1324 | pktcnt = skb_queue_len(&l->transmq) + skb_queue_len(&l->backlogq); |
1374 | msg_set_msgcnt(&tnlhdr, pktcnt); | 1325 | msg_set_msgcnt(&tnlhdr, pktcnt); |
@@ -1427,7 +1378,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1427 | if (tipc_link_is_blocked(l) || !xmitq) | 1378 | if (tipc_link_is_blocked(l) || !xmitq) |
1428 | goto exit; | 1379 | goto exit; |
1429 | 1380 | ||
1430 | if (link_own_addr(l) > msg_prevnode(hdr)) | 1381 | if (tipc_own_addr(l->net) > msg_prevnode(hdr)) |
1431 | l->net_plane = msg_net_plane(hdr); | 1382 | l->net_plane = msg_net_plane(hdr); |
1432 | 1383 | ||
1433 | switch (mtyp) { | 1384 | switch (mtyp) { |
@@ -1435,7 +1386,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1435 | 1386 | ||
1436 | /* Ignore duplicate RESET with old session number */ | 1387 | /* Ignore duplicate RESET with old session number */ |
1437 | if ((less_eq(msg_session(hdr), l->peer_session)) && | 1388 | if ((less_eq(msg_session(hdr), l->peer_session)) && |
1438 | (l->peer_session != WILDCARD_SESSION)) | 1389 | (l->peer_session != ANY_SESSION)) |
1439 | break; | 1390 | break; |
1440 | /* fall thru' */ | 1391 | /* fall thru' */ |
1441 | 1392 | ||
@@ -1479,6 +1430,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1479 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) | 1430 | if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) |
1480 | l->tolerance = peers_tol; | 1431 | l->tolerance = peers_tol; |
1481 | 1432 | ||
1433 | if (peers_prio && in_range(peers_prio, TIPC_MIN_LINK_PRI, | ||
1434 | TIPC_MAX_LINK_PRI)) { | ||
1435 | l->priority = peers_prio; | ||
1436 | rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | ||
1437 | } | ||
1438 | |||
1482 | l->silent_intv_cnt = 0; | 1439 | l->silent_intv_cnt = 0; |
1483 | l->stats.recv_states++; | 1440 | l->stats.recv_states++; |
1484 | if (msg_probe(hdr)) | 1441 | if (msg_probe(hdr)) |
@@ -1526,7 +1483,7 @@ static bool tipc_link_build_bc_proto_msg(struct tipc_link *l, bool bcast, | |||
1526 | u16 gap_to = peers_snd_nxt - 1; | 1483 | u16 gap_to = peers_snd_nxt - 1; |
1527 | 1484 | ||
1528 | skb = tipc_msg_create(BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, | 1485 | skb = tipc_msg_create(BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, |
1529 | 0, l->addr, link_own_addr(l), 0, 0, 0); | 1486 | 0, l->addr, tipc_own_addr(l->net), 0, 0, 0); |
1530 | if (!skb) | 1487 | if (!skb) |
1531 | return false; | 1488 | return false; |
1532 | hdr = buf_msg(skb); | 1489 | hdr = buf_msg(skb); |
@@ -1681,7 +1638,7 @@ int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1681 | if (mtyp != STATE_MSG) | 1638 | if (mtyp != STATE_MSG) |
1682 | return 0; | 1639 | return 0; |
1683 | 1640 | ||
1684 | if (dnode == link_own_addr(l)) { | 1641 | if (dnode == tipc_own_addr(l->net)) { |
1685 | tipc_link_bc_ack_rcv(l, acked, xmitq); | 1642 | tipc_link_bc_ack_rcv(l, acked, xmitq); |
1686 | rc = tipc_link_retrans(l->bc_sndlink, from, to, xmitq); | 1643 | rc = tipc_link_retrans(l->bc_sndlink, from, to, xmitq); |
1687 | l->stats.recv_nacks++; | 1644 | l->stats.recv_nacks++; |
@@ -2023,16 +1980,18 @@ msg_full: | |||
2023 | return -EMSGSIZE; | 1980 | return -EMSGSIZE; |
2024 | } | 1981 | } |
2025 | 1982 | ||
2026 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol) | 1983 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, |
1984 | struct sk_buff_head *xmitq) | ||
2027 | { | 1985 | { |
2028 | l->tolerance = tol; | 1986 | l->tolerance = tol; |
2029 | tipc_link_proto_xmit(l, STATE_MSG, 0, 0, tol, 0); | 1987 | tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, tol, 0, xmitq); |
2030 | } | 1988 | } |
2031 | 1989 | ||
2032 | void tipc_link_set_prio(struct tipc_link *l, u32 prio) | 1990 | void tipc_link_set_prio(struct tipc_link *l, u32 prio, |
1991 | struct sk_buff_head *xmitq) | ||
2033 | { | 1992 | { |
2034 | l->priority = prio; | 1993 | l->priority = prio; |
2035 | tipc_link_proto_xmit(l, STATE_MSG, 0, 0, 0, prio); | 1994 | tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, prio, xmitq); |
2036 | } | 1995 | } |
2037 | 1996 | ||
2038 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit) | 1997 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit) |
diff --git a/net/tipc/link.h b/net/tipc/link.h index b2ae0f4276af..6a94175ee20a 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -86,7 +86,6 @@ bool tipc_link_bc_create(struct net *net, u32 ownnode, u32 peer, | |||
86 | struct sk_buff_head *namedq, | 86 | struct sk_buff_head *namedq, |
87 | struct tipc_link *bc_sndlink, | 87 | struct tipc_link *bc_sndlink, |
88 | struct tipc_link **link); | 88 | struct tipc_link **link); |
89 | void tipc_link_reinit(struct tipc_link *l, u32 addr); | ||
90 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, | 89 | void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl, |
91 | int mtyp, struct sk_buff_head *xmitq); | 90 | int mtyp, struct sk_buff_head *xmitq); |
92 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); | 91 | void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq); |
@@ -112,8 +111,10 @@ char tipc_link_plane(struct tipc_link *l); | |||
112 | int tipc_link_prio(struct tipc_link *l); | 111 | int tipc_link_prio(struct tipc_link *l); |
113 | int tipc_link_window(struct tipc_link *l); | 112 | int tipc_link_window(struct tipc_link *l); |
114 | unsigned long tipc_link_tolerance(struct tipc_link *l); | 113 | unsigned long tipc_link_tolerance(struct tipc_link *l); |
115 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol); | 114 | void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, |
116 | void tipc_link_set_prio(struct tipc_link *l, u32 prio); | 115 | struct sk_buff_head *xmitq); |
116 | void tipc_link_set_prio(struct tipc_link *l, u32 prio, | ||
117 | struct sk_buff_head *xmitq); | ||
117 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit); | 118 | void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit); |
118 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); | 119 | void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); |
119 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, | 120 | int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 91fce70291a8..e190460fe0d3 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -47,12 +47,6 @@ | |||
47 | 47 | ||
48 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ | 48 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ |
49 | 49 | ||
50 | static const struct nla_policy | ||
51 | tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = { | ||
52 | [TIPC_NLA_NAME_TABLE_UNSPEC] = { .type = NLA_UNSPEC }, | ||
53 | [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED } | ||
54 | }; | ||
55 | |||
56 | /** | 50 | /** |
57 | * struct name_info - name sequence publication info | 51 | * struct name_info - name sequence publication info |
58 | * @node_list: circular list of publications made by own node | 52 | * @node_list: circular list of publications made by own node |
@@ -418,6 +412,9 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, | |||
418 | struct tipc_subscription *s) | 412 | struct tipc_subscription *s) |
419 | { | 413 | { |
420 | struct sub_seq *sseq = nseq->sseqs; | 414 | struct sub_seq *sseq = nseq->sseqs; |
415 | struct tipc_name_seq ns; | ||
416 | |||
417 | tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns); | ||
421 | 418 | ||
422 | list_add(&s->nameseq_list, &nseq->subscriptions); | 419 | list_add(&s->nameseq_list, &nseq->subscriptions); |
423 | 420 | ||
@@ -425,7 +422,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, | |||
425 | return; | 422 | return; |
426 | 423 | ||
427 | while (sseq != &nseq->sseqs[nseq->first_free]) { | 424 | while (sseq != &nseq->sseqs[nseq->first_free]) { |
428 | if (tipc_subscrp_check_overlap(s, sseq->lower, sseq->upper)) { | 425 | if (tipc_subscrp_check_overlap(&ns, sseq->lower, sseq->upper)) { |
429 | struct publication *crs; | 426 | struct publication *crs; |
430 | struct name_info *info = sseq->info; | 427 | struct name_info *info = sseq->info; |
431 | int must_report = 1; | 428 | int must_report = 1; |
@@ -722,9 +719,10 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, | |||
722 | void tipc_nametbl_subscribe(struct tipc_subscription *s) | 719 | void tipc_nametbl_subscribe(struct tipc_subscription *s) |
723 | { | 720 | { |
724 | struct tipc_net *tn = net_generic(s->net, tipc_net_id); | 721 | struct tipc_net *tn = net_generic(s->net, tipc_net_id); |
725 | u32 type = s->seq.type; | 722 | u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap); |
726 | int index = hash(type); | 723 | int index = hash(type); |
727 | struct name_seq *seq; | 724 | struct name_seq *seq; |
725 | struct tipc_name_seq ns; | ||
728 | 726 | ||
729 | spin_lock_bh(&tn->nametbl_lock); | 727 | spin_lock_bh(&tn->nametbl_lock); |
730 | seq = nametbl_find_seq(s->net, type); | 728 | seq = nametbl_find_seq(s->net, type); |
@@ -735,8 +733,9 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) | |||
735 | tipc_nameseq_subscribe(seq, s); | 733 | tipc_nameseq_subscribe(seq, s); |
736 | spin_unlock_bh(&seq->lock); | 734 | spin_unlock_bh(&seq->lock); |
737 | } else { | 735 | } else { |
736 | tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns); | ||
738 | pr_warn("Failed to create subscription for {%u,%u,%u}\n", | 737 | pr_warn("Failed to create subscription for {%u,%u,%u}\n", |
739 | s->seq.type, s->seq.lower, s->seq.upper); | 738 | ns.type, ns.lower, ns.upper); |
740 | } | 739 | } |
741 | spin_unlock_bh(&tn->nametbl_lock); | 740 | spin_unlock_bh(&tn->nametbl_lock); |
742 | } | 741 | } |
@@ -748,9 +747,10 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) | |||
748 | { | 747 | { |
749 | struct tipc_net *tn = net_generic(s->net, tipc_net_id); | 748 | struct tipc_net *tn = net_generic(s->net, tipc_net_id); |
750 | struct name_seq *seq; | 749 | struct name_seq *seq; |
750 | u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap); | ||
751 | 751 | ||
752 | spin_lock_bh(&tn->nametbl_lock); | 752 | spin_lock_bh(&tn->nametbl_lock); |
753 | seq = nametbl_find_seq(s->net, s->seq.type); | 753 | seq = nametbl_find_seq(s->net, type); |
754 | if (seq != NULL) { | 754 | if (seq != NULL) { |
755 | spin_lock_bh(&seq->lock); | 755 | spin_lock_bh(&seq->lock); |
756 | list_del_init(&s->nameseq_list); | 756 | list_del_init(&s->nameseq_list); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 77bf9113c7a7..28bf4feeb81c 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -41,11 +41,7 @@ | |||
41 | #include "socket.h" | 41 | #include "socket.h" |
42 | #include "node.h" | 42 | #include "node.h" |
43 | #include "bcast.h" | 43 | #include "bcast.h" |
44 | 44 | #include "netlink.h" | |
45 | static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { | ||
46 | [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, | ||
47 | [TIPC_NLA_NET_ID] = { .type = NLA_U32 } | ||
48 | }; | ||
49 | 45 | ||
50 | /* | 46 | /* |
51 | * The TIPC locking policy is designed to ensure a very fine locking | 47 | * The TIPC locking policy is designed to ensure a very fine locking |
@@ -116,7 +112,6 @@ int tipc_net_start(struct net *net, u32 addr) | |||
116 | tn->own_addr = addr; | 112 | tn->own_addr = addr; |
117 | tipc_named_reinit(net); | 113 | tipc_named_reinit(net); |
118 | tipc_sk_reinit(net); | 114 | tipc_sk_reinit(net); |
119 | tipc_bcast_reinit(net); | ||
120 | 115 | ||
121 | tipc_nametbl_publish(net, TIPC_CFG_SRV, tn->own_addr, tn->own_addr, | 116 | tipc_nametbl_publish(net, TIPC_CFG_SRV, tn->own_addr, tn->own_addr, |
122 | TIPC_ZONE_SCOPE, 0, tn->own_addr); | 117 | TIPC_ZONE_SCOPE, 0, tn->own_addr); |
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c index 8975b0135b76..56935df2167a 100644 --- a/net/tipc/netlink.c +++ b/net/tipc/netlink.c | |||
@@ -55,6 +55,75 @@ static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = { | |||
55 | [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, } | 55 | [TIPC_NLA_NAME_TABLE] = { .type = NLA_NESTED, } |
56 | }; | 56 | }; |
57 | 57 | ||
58 | const struct nla_policy | ||
59 | tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = { | ||
60 | [TIPC_NLA_NAME_TABLE_UNSPEC] = { .type = NLA_UNSPEC }, | ||
61 | [TIPC_NLA_NAME_TABLE_PUBL] = { .type = NLA_NESTED } | ||
62 | }; | ||
63 | |||
64 | const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { | ||
65 | [TIPC_NLA_SOCK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
66 | [TIPC_NLA_SOCK_ADDR] = { .type = NLA_U32 }, | ||
67 | [TIPC_NLA_SOCK_REF] = { .type = NLA_U32 }, | ||
68 | [TIPC_NLA_SOCK_CON] = { .type = NLA_NESTED }, | ||
69 | [TIPC_NLA_SOCK_HAS_PUBL] = { .type = NLA_FLAG } | ||
70 | }; | ||
71 | |||
72 | const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = { | ||
73 | [TIPC_NLA_NET_UNSPEC] = { .type = NLA_UNSPEC }, | ||
74 | [TIPC_NLA_NET_ID] = { .type = NLA_U32 } | ||
75 | }; | ||
76 | |||
77 | const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | ||
78 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
79 | [TIPC_NLA_LINK_NAME] = { .type = NLA_STRING, | ||
80 | .len = TIPC_MAX_LINK_NAME }, | ||
81 | [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 }, | ||
82 | [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG }, | ||
83 | [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG }, | ||
84 | [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG }, | ||
85 | [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED }, | ||
86 | [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED }, | ||
87 | [TIPC_NLA_LINK_RX] = { .type = NLA_U32 }, | ||
88 | [TIPC_NLA_LINK_TX] = { .type = NLA_U32 } | ||
89 | }; | ||
90 | |||
91 | const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { | ||
92 | [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, | ||
93 | [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, | ||
94 | [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } | ||
95 | }; | ||
96 | |||
97 | /* Properties valid for media, bearer and link */ | ||
98 | const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { | ||
99 | [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, | ||
100 | [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, | ||
101 | [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, | ||
102 | [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 } | ||
103 | }; | ||
104 | |||
105 | const struct nla_policy tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1] = { | ||
106 | [TIPC_NLA_BEARER_UNSPEC] = { .type = NLA_UNSPEC }, | ||
107 | [TIPC_NLA_BEARER_NAME] = { .type = NLA_STRING, | ||
108 | .len = TIPC_MAX_BEARER_NAME }, | ||
109 | [TIPC_NLA_BEARER_PROP] = { .type = NLA_NESTED }, | ||
110 | [TIPC_NLA_BEARER_DOMAIN] = { .type = NLA_U32 } | ||
111 | }; | ||
112 | |||
113 | const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = { | ||
114 | [TIPC_NLA_MEDIA_UNSPEC] = { .type = NLA_UNSPEC }, | ||
115 | [TIPC_NLA_MEDIA_NAME] = { .type = NLA_STRING }, | ||
116 | [TIPC_NLA_MEDIA_PROP] = { .type = NLA_NESTED } | ||
117 | }; | ||
118 | |||
119 | const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { | ||
120 | [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, | ||
121 | [TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY, | ||
122 | .len = sizeof(struct sockaddr_storage)}, | ||
123 | [TIPC_NLA_UDP_REMOTE] = {.type = NLA_BINARY, | ||
124 | .len = sizeof(struct sockaddr_storage)}, | ||
125 | }; | ||
126 | |||
58 | /* Users of the legacy API (tipc-config) can't handle that we add operations, | 127 | /* Users of the legacy API (tipc-config) can't handle that we add operations, |
59 | * so we have a separate genl handling for the new API. | 128 | * so we have a separate genl handling for the new API. |
60 | */ | 129 | */ |
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h index 08a1db67b927..ed1dbcb4afbd 100644 --- a/net/tipc/netlink.h +++ b/net/tipc/netlink.h | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #ifndef _TIPC_NETLINK_H | 36 | #ifndef _TIPC_NETLINK_H |
37 | #define _TIPC_NETLINK_H | 37 | #define _TIPC_NETLINK_H |
38 | #include <net/netlink.h> | ||
38 | 39 | ||
39 | extern struct genl_family tipc_genl_family; | 40 | extern struct genl_family tipc_genl_family; |
40 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf); | 41 | int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf); |
@@ -45,6 +46,16 @@ struct tipc_nl_msg { | |||
45 | u32 seq; | 46 | u32 seq; |
46 | }; | 47 | }; |
47 | 48 | ||
49 | extern const struct nla_policy tipc_nl_name_table_policy[]; | ||
50 | extern const struct nla_policy tipc_nl_sock_policy[]; | ||
51 | extern const struct nla_policy tipc_nl_net_policy[]; | ||
52 | extern const struct nla_policy tipc_nl_link_policy[]; | ||
53 | extern const struct nla_policy tipc_nl_node_policy[]; | ||
54 | extern const struct nla_policy tipc_nl_prop_policy[]; | ||
55 | extern const struct nla_policy tipc_nl_bearer_policy[]; | ||
56 | extern const struct nla_policy tipc_nl_media_policy[]; | ||
57 | extern const struct nla_policy tipc_nl_udp_policy[]; | ||
58 | |||
48 | int tipc_netlink_start(void); | 59 | int tipc_netlink_start(void); |
49 | int tipc_netlink_compat_start(void); | 60 | int tipc_netlink_compat_start(void); |
50 | void tipc_netlink_stop(void); | 61 | void tipc_netlink_stop(void); |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 2c016fdefe97..d7d050f44fc1 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
@@ -1104,8 +1104,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
1104 | req_nlh = (struct nlmsghdr *)skb->data; | 1104 | req_nlh = (struct nlmsghdr *)skb->data; |
1105 | msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; | 1105 | msg.req = nlmsg_data(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN; |
1106 | msg.cmd = req_userhdr->cmd; | 1106 | msg.cmd = req_userhdr->cmd; |
1107 | msg.dst_sk = info->dst_sk; | ||
1108 | msg.net = genl_info_net(info); | 1107 | msg.net = genl_info_net(info); |
1108 | msg.dst_sk = skb->sk; | ||
1109 | 1109 | ||
1110 | if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { | 1110 | if ((msg.cmd & 0xC000) && (!netlink_net_capable(skb, CAP_NET_ADMIN))) { |
1111 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); | 1111 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_NET_ADMIN); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 9d7a16fc5ca4..ace178fd3850 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "socket.h" | 41 | #include "socket.h" |
42 | #include "bcast.h" | 42 | #include "bcast.h" |
43 | #include "discover.h" | 43 | #include "discover.h" |
44 | #include "netlink.h" | ||
44 | 45 | ||
45 | #define INVALID_NODE_SIG 0x10000 | 46 | #define INVALID_NODE_SIG 0x10000 |
46 | 47 | ||
@@ -164,28 +165,6 @@ struct tipc_sock_conn { | |||
164 | struct list_head list; | 165 | struct list_head list; |
165 | }; | 166 | }; |
166 | 167 | ||
167 | static const struct nla_policy tipc_nl_link_policy[TIPC_NLA_LINK_MAX + 1] = { | ||
168 | [TIPC_NLA_LINK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
169 | [TIPC_NLA_LINK_NAME] = { | ||
170 | .type = NLA_STRING, | ||
171 | .len = TIPC_MAX_LINK_NAME | ||
172 | }, | ||
173 | [TIPC_NLA_LINK_MTU] = { .type = NLA_U32 }, | ||
174 | [TIPC_NLA_LINK_BROADCAST] = { .type = NLA_FLAG }, | ||
175 | [TIPC_NLA_LINK_UP] = { .type = NLA_FLAG }, | ||
176 | [TIPC_NLA_LINK_ACTIVE] = { .type = NLA_FLAG }, | ||
177 | [TIPC_NLA_LINK_PROP] = { .type = NLA_NESTED }, | ||
178 | [TIPC_NLA_LINK_STATS] = { .type = NLA_NESTED }, | ||
179 | [TIPC_NLA_LINK_RX] = { .type = NLA_U32 }, | ||
180 | [TIPC_NLA_LINK_TX] = { .type = NLA_U32 } | ||
181 | }; | ||
182 | |||
183 | static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { | ||
184 | [TIPC_NLA_NODE_UNSPEC] = { .type = NLA_UNSPEC }, | ||
185 | [TIPC_NLA_NODE_ADDR] = { .type = NLA_U32 }, | ||
186 | [TIPC_NLA_NODE_UP] = { .type = NLA_FLAG } | ||
187 | }; | ||
188 | |||
189 | static struct tipc_link *node_active_link(struct tipc_node *n, int sel) | 168 | static struct tipc_link *node_active_link(struct tipc_node *n, int sel) |
190 | { | 169 | { |
191 | int bearer_id = n->active_links[sel & 1]; | 170 | int bearer_id = n->active_links[sel & 1]; |
@@ -225,9 +204,10 @@ static unsigned int tipc_hashfn(u32 addr) | |||
225 | 204 | ||
226 | static void tipc_node_kref_release(struct kref *kref) | 205 | static void tipc_node_kref_release(struct kref *kref) |
227 | { | 206 | { |
228 | struct tipc_node *node = container_of(kref, struct tipc_node, kref); | 207 | struct tipc_node *n = container_of(kref, struct tipc_node, kref); |
229 | 208 | ||
230 | tipc_node_delete(node); | 209 | kfree(n->bc_entry.link); |
210 | kfree_rcu(n, rcu); | ||
231 | } | 211 | } |
232 | 212 | ||
233 | static void tipc_node_put(struct tipc_node *node) | 213 | static void tipc_node_put(struct tipc_node *node) |
@@ -245,23 +225,23 @@ static void tipc_node_get(struct tipc_node *node) | |||
245 | */ | 225 | */ |
246 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr) | 226 | static struct tipc_node *tipc_node_find(struct net *net, u32 addr) |
247 | { | 227 | { |
248 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 228 | struct tipc_net *tn = tipc_net(net); |
249 | struct tipc_node *node; | 229 | struct tipc_node *node; |
230 | unsigned int thash = tipc_hashfn(addr); | ||
250 | 231 | ||
251 | if (unlikely(!in_own_cluster_exact(net, addr))) | 232 | if (unlikely(!in_own_cluster_exact(net, addr))) |
252 | return NULL; | 233 | return NULL; |
253 | 234 | ||
254 | rcu_read_lock(); | 235 | rcu_read_lock(); |
255 | hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)], | 236 | hlist_for_each_entry_rcu(node, &tn->node_htable[thash], hash) { |
256 | hash) { | 237 | if (node->addr != addr) |
257 | if (node->addr == addr) { | 238 | continue; |
258 | tipc_node_get(node); | 239 | if (!kref_get_unless_zero(&node->kref)) |
259 | rcu_read_unlock(); | 240 | node = NULL; |
260 | return node; | 241 | break; |
261 | } | ||
262 | } | 242 | } |
263 | rcu_read_unlock(); | 243 | rcu_read_unlock(); |
264 | return NULL; | 244 | return node; |
265 | } | 245 | } |
266 | 246 | ||
267 | static void tipc_node_read_lock(struct tipc_node *n) | 247 | static void tipc_node_read_lock(struct tipc_node *n) |
@@ -395,21 +375,20 @@ static void tipc_node_delete(struct tipc_node *node) | |||
395 | { | 375 | { |
396 | list_del_rcu(&node->list); | 376 | list_del_rcu(&node->list); |
397 | hlist_del_rcu(&node->hash); | 377 | hlist_del_rcu(&node->hash); |
398 | kfree(node->bc_entry.link); | 378 | tipc_node_put(node); |
399 | kfree_rcu(node, rcu); | 379 | |
380 | del_timer_sync(&node->timer); | ||
381 | tipc_node_put(node); | ||
400 | } | 382 | } |
401 | 383 | ||
402 | void tipc_node_stop(struct net *net) | 384 | void tipc_node_stop(struct net *net) |
403 | { | 385 | { |
404 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 386 | struct tipc_net *tn = tipc_net(net); |
405 | struct tipc_node *node, *t_node; | 387 | struct tipc_node *node, *t_node; |
406 | 388 | ||
407 | spin_lock_bh(&tn->node_list_lock); | 389 | spin_lock_bh(&tn->node_list_lock); |
408 | list_for_each_entry_safe(node, t_node, &tn->node_list, list) { | 390 | list_for_each_entry_safe(node, t_node, &tn->node_list, list) |
409 | if (del_timer(&node->timer)) | 391 | tipc_node_delete(node); |
410 | tipc_node_put(node); | ||
411 | tipc_node_put(node); | ||
412 | } | ||
413 | spin_unlock_bh(&tn->node_list_lock); | 392 | spin_unlock_bh(&tn->node_list_lock); |
414 | } | 393 | } |
415 | 394 | ||
@@ -530,9 +509,7 @@ static void tipc_node_timeout(unsigned long data) | |||
530 | if (rc & TIPC_LINK_DOWN_EVT) | 509 | if (rc & TIPC_LINK_DOWN_EVT) |
531 | tipc_node_link_down(n, bearer_id, false); | 510 | tipc_node_link_down(n, bearer_id, false); |
532 | } | 511 | } |
533 | if (!mod_timer(&n->timer, jiffies + n->keepalive_intv)) | 512 | mod_timer(&n->timer, jiffies + n->keepalive_intv); |
534 | tipc_node_get(n); | ||
535 | tipc_node_put(n); | ||
536 | } | 513 | } |
537 | 514 | ||
538 | /** | 515 | /** |
@@ -845,7 +822,7 @@ void tipc_node_check_dest(struct net *net, u32 onode, | |||
845 | memcpy(&le->maddr, maddr, sizeof(*maddr)); | 822 | memcpy(&le->maddr, maddr, sizeof(*maddr)); |
846 | exit: | 823 | exit: |
847 | tipc_node_write_unlock(n); | 824 | tipc_node_write_unlock(n); |
848 | if (reset && !tipc_link_is_reset(l)) | 825 | if (reset && l && !tipc_link_is_reset(l)) |
849 | tipc_node_link_down(n, b->identity, false); | 826 | tipc_node_link_down(n, b->identity, false); |
850 | tipc_node_put(n); | 827 | tipc_node_put(n); |
851 | } | 828 | } |
@@ -1166,7 +1143,7 @@ msg_full: | |||
1166 | * @dnode: address of destination node | 1143 | * @dnode: address of destination node |
1167 | * @selector: a number used for deterministic link selection | 1144 | * @selector: a number used for deterministic link selection |
1168 | * Consumes the buffer chain, except when returning -ELINKCONG | 1145 | * Consumes the buffer chain, except when returning -ELINKCONG |
1169 | * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE | 1146 | * Returns 0 if success, otherwise: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE,-ENOBUF |
1170 | */ | 1147 | */ |
1171 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, | 1148 | int tipc_node_xmit(struct net *net, struct sk_buff_head *list, |
1172 | u32 dnode, int selector) | 1149 | u32 dnode, int selector) |
@@ -1174,33 +1151,43 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, | |||
1174 | struct tipc_link_entry *le = NULL; | 1151 | struct tipc_link_entry *le = NULL; |
1175 | struct tipc_node *n; | 1152 | struct tipc_node *n; |
1176 | struct sk_buff_head xmitq; | 1153 | struct sk_buff_head xmitq; |
1177 | int bearer_id = -1; | 1154 | int bearer_id; |
1178 | int rc = -EHOSTUNREACH; | 1155 | int rc; |
1156 | |||
1157 | if (in_own_node(net, dnode)) { | ||
1158 | tipc_sk_rcv(net, list); | ||
1159 | return 0; | ||
1160 | } | ||
1179 | 1161 | ||
1180 | __skb_queue_head_init(&xmitq); | ||
1181 | n = tipc_node_find(net, dnode); | 1162 | n = tipc_node_find(net, dnode); |
1182 | if (likely(n)) { | 1163 | if (unlikely(!n)) { |
1183 | tipc_node_read_lock(n); | 1164 | skb_queue_purge(list); |
1184 | bearer_id = n->active_links[selector & 1]; | 1165 | return -EHOSTUNREACH; |
1185 | if (bearer_id >= 0) { | 1166 | } |
1186 | le = &n->links[bearer_id]; | 1167 | |
1187 | spin_lock_bh(&le->lock); | 1168 | tipc_node_read_lock(n); |
1188 | rc = tipc_link_xmit(le->link, list, &xmitq); | 1169 | bearer_id = n->active_links[selector & 1]; |
1189 | spin_unlock_bh(&le->lock); | 1170 | if (unlikely(bearer_id == INVALID_BEARER_ID)) { |
1190 | } | ||
1191 | tipc_node_read_unlock(n); | 1171 | tipc_node_read_unlock(n); |
1192 | if (likely(!rc)) | ||
1193 | tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); | ||
1194 | else if (rc == -ENOBUFS) | ||
1195 | tipc_node_link_down(n, bearer_id, false); | ||
1196 | tipc_node_put(n); | 1172 | tipc_node_put(n); |
1197 | return rc; | 1173 | skb_queue_purge(list); |
1174 | return -EHOSTUNREACH; | ||
1198 | } | 1175 | } |
1199 | 1176 | ||
1200 | if (likely(in_own_node(net, dnode))) { | 1177 | __skb_queue_head_init(&xmitq); |
1201 | tipc_sk_rcv(net, list); | 1178 | le = &n->links[bearer_id]; |
1202 | return 0; | 1179 | spin_lock_bh(&le->lock); |
1203 | } | 1180 | rc = tipc_link_xmit(le->link, list, &xmitq); |
1181 | spin_unlock_bh(&le->lock); | ||
1182 | tipc_node_read_unlock(n); | ||
1183 | |||
1184 | if (likely(rc == 0)) | ||
1185 | tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr); | ||
1186 | else if (rc == -ENOBUFS) | ||
1187 | tipc_node_link_down(n, bearer_id, false); | ||
1188 | |||
1189 | tipc_node_put(n); | ||
1190 | |||
1204 | return rc; | 1191 | return rc; |
1205 | } | 1192 | } |
1206 | 1193 | ||
@@ -1637,9 +1624,12 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) | |||
1637 | char *name; | 1624 | char *name; |
1638 | struct tipc_link *link; | 1625 | struct tipc_link *link; |
1639 | struct tipc_node *node; | 1626 | struct tipc_node *node; |
1627 | struct sk_buff_head xmitq; | ||
1640 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; | 1628 | struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; |
1641 | struct net *net = sock_net(skb->sk); | 1629 | struct net *net = sock_net(skb->sk); |
1642 | 1630 | ||
1631 | __skb_queue_head_init(&xmitq); | ||
1632 | |||
1643 | if (!info->attrs[TIPC_NLA_LINK]) | 1633 | if (!info->attrs[TIPC_NLA_LINK]) |
1644 | return -EINVAL; | 1634 | return -EINVAL; |
1645 | 1635 | ||
@@ -1683,13 +1673,13 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) | |||
1683 | u32 tol; | 1673 | u32 tol; |
1684 | 1674 | ||
1685 | tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); | 1675 | tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); |
1686 | tipc_link_set_tolerance(link, tol); | 1676 | tipc_link_set_tolerance(link, tol, &xmitq); |
1687 | } | 1677 | } |
1688 | if (props[TIPC_NLA_PROP_PRIO]) { | 1678 | if (props[TIPC_NLA_PROP_PRIO]) { |
1689 | u32 prio; | 1679 | u32 prio; |
1690 | 1680 | ||
1691 | prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); | 1681 | prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); |
1692 | tipc_link_set_prio(link, prio); | 1682 | tipc_link_set_prio(link, prio, &xmitq); |
1693 | } | 1683 | } |
1694 | if (props[TIPC_NLA_PROP_WIN]) { | 1684 | if (props[TIPC_NLA_PROP_WIN]) { |
1695 | u32 win; | 1685 | u32 win; |
@@ -1701,7 +1691,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) | |||
1701 | 1691 | ||
1702 | out: | 1692 | out: |
1703 | tipc_node_read_unlock(node); | 1693 | tipc_node_read_unlock(node); |
1704 | 1694 | tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr); | |
1705 | return res; | 1695 | return res; |
1706 | } | 1696 | } |
1707 | 1697 | ||
diff --git a/net/tipc/server.c b/net/tipc/server.c index 922e04a43396..2446bfbaa309 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
@@ -571,13 +571,13 @@ static void tipc_work_stop(struct tipc_server *s) | |||
571 | 571 | ||
572 | static int tipc_work_start(struct tipc_server *s) | 572 | static int tipc_work_start(struct tipc_server *s) |
573 | { | 573 | { |
574 | s->rcv_wq = alloc_workqueue("tipc_rcv", WQ_UNBOUND, 1); | 574 | s->rcv_wq = alloc_ordered_workqueue("tipc_rcv", 0); |
575 | if (!s->rcv_wq) { | 575 | if (!s->rcv_wq) { |
576 | pr_err("can't start tipc receive workqueue\n"); | 576 | pr_err("can't start tipc receive workqueue\n"); |
577 | return -ENOMEM; | 577 | return -ENOMEM; |
578 | } | 578 | } |
579 | 579 | ||
580 | s->send_wq = alloc_workqueue("tipc_send", WQ_UNBOUND, 1); | 580 | s->send_wq = alloc_ordered_workqueue("tipc_send", 0); |
581 | if (!s->send_wq) { | 581 | if (!s->send_wq) { |
582 | pr_err("can't start tipc send workqueue\n"); | 582 | pr_err("can't start tipc send workqueue\n"); |
583 | destroy_workqueue(s->rcv_wq); | 583 | destroy_workqueue(s->rcv_wq); |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 4d420bb27396..3eeb50a27b89 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "name_distr.h" | 42 | #include "name_distr.h" |
43 | #include "socket.h" | 43 | #include "socket.h" |
44 | #include "bcast.h" | 44 | #include "bcast.h" |
45 | #include "netlink.h" | ||
45 | 46 | ||
46 | #define SS_LISTENING -1 /* socket is listening */ | 47 | #define SS_LISTENING -1 /* socket is listening */ |
47 | #define SS_READY -2 /* socket is connectionless */ | 48 | #define SS_READY -2 /* socket is connectionless */ |
@@ -126,14 +127,6 @@ static const struct proto_ops stream_ops; | |||
126 | static const struct proto_ops msg_ops; | 127 | static const struct proto_ops msg_ops; |
127 | static struct proto tipc_proto; | 128 | static struct proto tipc_proto; |
128 | 129 | ||
129 | static const struct nla_policy tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { | ||
130 | [TIPC_NLA_SOCK_UNSPEC] = { .type = NLA_UNSPEC }, | ||
131 | [TIPC_NLA_SOCK_ADDR] = { .type = NLA_U32 }, | ||
132 | [TIPC_NLA_SOCK_REF] = { .type = NLA_U32 }, | ||
133 | [TIPC_NLA_SOCK_CON] = { .type = NLA_NESTED }, | ||
134 | [TIPC_NLA_SOCK_HAS_PUBL] = { .type = NLA_FLAG } | ||
135 | }; | ||
136 | |||
137 | static const struct rhashtable_params tsk_rht_params; | 130 | static const struct rhashtable_params tsk_rht_params; |
138 | 131 | ||
139 | /* | 132 | /* |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index f9ff73a8d815..e6cb386fbf34 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -92,25 +92,42 @@ static void tipc_subscrp_send_event(struct tipc_subscription *sub, | |||
92 | * | 92 | * |
93 | * Returns 1 if there is overlap, otherwise 0. | 93 | * Returns 1 if there is overlap, otherwise 0. |
94 | */ | 94 | */ |
95 | int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, | 95 | int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower, |
96 | u32 found_upper) | 96 | u32 found_upper) |
97 | { | 97 | { |
98 | if (found_lower < sub->seq.lower) | 98 | if (found_lower < seq->lower) |
99 | found_lower = sub->seq.lower; | 99 | found_lower = seq->lower; |
100 | if (found_upper > sub->seq.upper) | 100 | if (found_upper > seq->upper) |
101 | found_upper = sub->seq.upper; | 101 | found_upper = seq->upper; |
102 | if (found_lower > found_upper) | 102 | if (found_lower > found_upper) |
103 | return 0; | 103 | return 0; |
104 | return 1; | 104 | return 1; |
105 | } | 105 | } |
106 | 106 | ||
107 | u32 tipc_subscrp_convert_seq_type(u32 type, int swap) | ||
108 | { | ||
109 | return htohl(type, swap); | ||
110 | } | ||
111 | |||
112 | void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, | ||
113 | struct tipc_name_seq *out) | ||
114 | { | ||
115 | out->type = htohl(in->type, swap); | ||
116 | out->lower = htohl(in->lower, swap); | ||
117 | out->upper = htohl(in->upper, swap); | ||
118 | } | ||
119 | |||
107 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, | 120 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, |
108 | u32 found_upper, u32 event, u32 port_ref, | 121 | u32 found_upper, u32 event, u32 port_ref, |
109 | u32 node, int must) | 122 | u32 node, int must) |
110 | { | 123 | { |
111 | if (!tipc_subscrp_check_overlap(sub, found_lower, found_upper)) | 124 | struct tipc_name_seq seq; |
125 | |||
126 | tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq); | ||
127 | if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper)) | ||
112 | return; | 128 | return; |
113 | if (!must && !(sub->filter & TIPC_SUB_PORTS)) | 129 | if (!must && |
130 | !(htohl(sub->evt.s.filter, sub->swap) & TIPC_SUB_PORTS)) | ||
114 | return; | 131 | return; |
115 | 132 | ||
116 | tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, | 133 | tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, |
@@ -171,12 +188,14 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid) | |||
171 | static void tipc_subscrb_delete(struct tipc_subscriber *subscriber) | 188 | static void tipc_subscrb_delete(struct tipc_subscriber *subscriber) |
172 | { | 189 | { |
173 | struct tipc_subscription *sub, *temp; | 190 | struct tipc_subscription *sub, *temp; |
191 | u32 timeout; | ||
174 | 192 | ||
175 | spin_lock_bh(&subscriber->lock); | 193 | spin_lock_bh(&subscriber->lock); |
176 | /* Destroy any existing subscriptions for subscriber */ | 194 | /* Destroy any existing subscriptions for subscriber */ |
177 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, | 195 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, |
178 | subscrp_list) { | 196 | subscrp_list) { |
179 | if (del_timer(&sub->timer)) { | 197 | timeout = htohl(sub->evt.s.timeout, sub->swap); |
198 | if ((timeout == TIPC_WAIT_FOREVER) || del_timer(&sub->timer)) { | ||
180 | tipc_subscrp_delete(sub); | 199 | tipc_subscrp_delete(sub); |
181 | tipc_subscrb_put(subscriber); | 200 | tipc_subscrb_put(subscriber); |
182 | } | 201 | } |
@@ -200,13 +219,16 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, | |||
200 | struct tipc_subscriber *subscriber) | 219 | struct tipc_subscriber *subscriber) |
201 | { | 220 | { |
202 | struct tipc_subscription *sub, *temp; | 221 | struct tipc_subscription *sub, *temp; |
222 | u32 timeout; | ||
203 | 223 | ||
204 | spin_lock_bh(&subscriber->lock); | 224 | spin_lock_bh(&subscriber->lock); |
205 | /* Find first matching subscription, exit if not found */ | 225 | /* Find first matching subscription, exit if not found */ |
206 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, | 226 | list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, |
207 | subscrp_list) { | 227 | subscrp_list) { |
208 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { | 228 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { |
209 | if (del_timer(&sub->timer)) { | 229 | timeout = htohl(sub->evt.s.timeout, sub->swap); |
230 | if ((timeout == TIPC_WAIT_FOREVER) || | ||
231 | del_timer(&sub->timer)) { | ||
210 | tipc_subscrp_delete(sub); | 232 | tipc_subscrp_delete(sub); |
211 | tipc_subscrb_put(subscriber); | 233 | tipc_subscrb_put(subscriber); |
212 | } | 234 | } |
@@ -216,66 +238,67 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, | |||
216 | spin_unlock_bh(&subscriber->lock); | 238 | spin_unlock_bh(&subscriber->lock); |
217 | } | 239 | } |
218 | 240 | ||
219 | static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, | 241 | static struct tipc_subscription *tipc_subscrp_create(struct net *net, |
220 | struct tipc_subscriber *subscriber, | 242 | struct tipc_subscr *s, |
221 | struct tipc_subscription **sub_p) | 243 | int swap) |
222 | { | 244 | { |
223 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 245 | struct tipc_net *tn = net_generic(net, tipc_net_id); |
224 | struct tipc_subscription *sub; | 246 | struct tipc_subscription *sub; |
225 | int swap; | 247 | u32 filter = htohl(s->filter, swap); |
226 | |||
227 | /* Determine subscriber's endianness */ | ||
228 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); | ||
229 | |||
230 | /* Detect & process a subscription cancellation request */ | ||
231 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | ||
232 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | ||
233 | tipc_subscrp_cancel(s, subscriber); | ||
234 | return 0; | ||
235 | } | ||
236 | 248 | ||
237 | /* Refuse subscription if global limit exceeded */ | 249 | /* Refuse subscription if global limit exceeded */ |
238 | if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { | 250 | if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { |
239 | pr_warn("Subscription rejected, limit reached (%u)\n", | 251 | pr_warn("Subscription rejected, limit reached (%u)\n", |
240 | TIPC_MAX_SUBSCRIPTIONS); | 252 | TIPC_MAX_SUBSCRIPTIONS); |
241 | return -EINVAL; | 253 | return NULL; |
242 | } | 254 | } |
243 | 255 | ||
244 | /* Allocate subscription object */ | 256 | /* Allocate subscription object */ |
245 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); | 257 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); |
246 | if (!sub) { | 258 | if (!sub) { |
247 | pr_warn("Subscription rejected, no memory\n"); | 259 | pr_warn("Subscription rejected, no memory\n"); |
248 | return -ENOMEM; | 260 | return NULL; |
249 | } | 261 | } |
250 | 262 | ||
251 | /* Initialize subscription object */ | 263 | /* Initialize subscription object */ |
252 | sub->net = net; | 264 | sub->net = net; |
253 | sub->seq.type = htohl(s->seq.type, swap); | 265 | if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) || |
254 | sub->seq.lower = htohl(s->seq.lower, swap); | 266 | (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) { |
255 | sub->seq.upper = htohl(s->seq.upper, swap); | ||
256 | sub->timeout = msecs_to_jiffies(htohl(s->timeout, swap)); | ||
257 | sub->filter = htohl(s->filter, swap); | ||
258 | if ((!(sub->filter & TIPC_SUB_PORTS) == | ||
259 | !(sub->filter & TIPC_SUB_SERVICE)) || | ||
260 | (sub->seq.lower > sub->seq.upper)) { | ||
261 | pr_warn("Subscription rejected, illegal request\n"); | 267 | pr_warn("Subscription rejected, illegal request\n"); |
262 | kfree(sub); | 268 | kfree(sub); |
263 | return -EINVAL; | 269 | return NULL; |
264 | } | 270 | } |
265 | spin_lock_bh(&subscriber->lock); | 271 | |
266 | list_add(&sub->subscrp_list, &subscriber->subscrp_list); | ||
267 | spin_unlock_bh(&subscriber->lock); | ||
268 | sub->subscriber = subscriber; | ||
269 | sub->swap = swap; | 272 | sub->swap = swap; |
270 | memcpy(&sub->evt.s, s, sizeof(*s)); | 273 | memcpy(&sub->evt.s, s, sizeof(*s)); |
271 | atomic_inc(&tn->subscription_count); | 274 | atomic_inc(&tn->subscription_count); |
275 | return sub; | ||
276 | } | ||
277 | |||
278 | static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, | ||
279 | struct tipc_subscriber *subscriber, int swap) | ||
280 | { | ||
281 | struct tipc_net *tn = net_generic(net, tipc_net_id); | ||
282 | struct tipc_subscription *sub = NULL; | ||
283 | u32 timeout; | ||
284 | |||
285 | sub = tipc_subscrp_create(net, s, swap); | ||
286 | if (!sub) | ||
287 | return tipc_conn_terminate(tn->topsrv, subscriber->conid); | ||
288 | |||
289 | spin_lock_bh(&subscriber->lock); | ||
290 | list_add(&sub->subscrp_list, &subscriber->subscrp_list); | ||
291 | tipc_subscrb_get(subscriber); | ||
292 | sub->subscriber = subscriber; | ||
293 | tipc_nametbl_subscribe(sub); | ||
294 | spin_unlock_bh(&subscriber->lock); | ||
295 | |||
296 | timeout = htohl(sub->evt.s.timeout, swap); | ||
297 | if (timeout == TIPC_WAIT_FOREVER) | ||
298 | return; | ||
299 | |||
272 | setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); | 300 | setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); |
273 | if (sub->timeout != TIPC_WAIT_FOREVER) | 301 | mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); |
274 | sub->timeout += jiffies; | ||
275 | if (!mod_timer(&sub->timer, sub->timeout)) | ||
276 | tipc_subscrb_get(subscriber); | ||
277 | *sub_p = sub; | ||
278 | return 0; | ||
279 | } | 302 | } |
280 | 303 | ||
281 | /* Handle one termination request for the subscriber */ | 304 | /* Handle one termination request for the subscriber */ |
@@ -289,15 +312,22 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, | |||
289 | struct sockaddr_tipc *addr, void *usr_data, | 312 | struct sockaddr_tipc *addr, void *usr_data, |
290 | void *buf, size_t len) | 313 | void *buf, size_t len) |
291 | { | 314 | { |
292 | struct tipc_subscriber *subscrb = usr_data; | 315 | struct tipc_subscriber *subscriber = usr_data; |
293 | struct tipc_subscription *sub = NULL; | 316 | struct tipc_subscr *s = (struct tipc_subscr *)buf; |
294 | struct tipc_net *tn = net_generic(net, tipc_net_id); | 317 | int swap; |
295 | 318 | ||
296 | if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub)) | 319 | /* Determine subscriber's endianness */ |
297 | return tipc_conn_terminate(tn->topsrv, subscrb->conid); | 320 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE | |
321 | TIPC_SUB_CANCEL)); | ||
322 | |||
323 | /* Detect & process a subscription cancellation request */ | ||
324 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | ||
325 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | ||
326 | return tipc_subscrp_cancel(s, subscriber); | ||
327 | } | ||
298 | 328 | ||
299 | if (sub) | 329 | if (s) |
300 | tipc_nametbl_subscribe(sub); | 330 | tipc_subscrp_subscribe(net, s, subscriber, swap); |
301 | } | 331 | } |
302 | 332 | ||
303 | /* Handle one request to establish a new subscriber */ | 333 | /* Handle one request to establish a new subscriber */ |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 92ee18cc5fe6..be60103082c9 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -50,21 +50,15 @@ struct tipc_subscriber; | |||
50 | * @subscriber: pointer to its subscriber | 50 | * @subscriber: pointer to its subscriber |
51 | * @seq: name sequence associated with subscription | 51 | * @seq: name sequence associated with subscription |
52 | * @net: point to network namespace | 52 | * @net: point to network namespace |
53 | * @timeout: duration of subscription (in ms) | ||
54 | * @filter: event filtering to be done for subscription | ||
55 | * @timer: timer governing subscription duration (optional) | 53 | * @timer: timer governing subscription duration (optional) |
56 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 54 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
57 | * @subscrp_list: adjacent subscriptions in subscriber's subscription list | 55 | * @subscrp_list: adjacent subscriptions in subscriber's subscription list |
58 | * @server_ref: object reference of server port associated with subscription | ||
59 | * @swap: indicates if subscriber uses opposite endianness in its messages | 56 | * @swap: indicates if subscriber uses opposite endianness in its messages |
60 | * @evt: template for events generated by subscription | 57 | * @evt: template for events generated by subscription |
61 | */ | 58 | */ |
62 | struct tipc_subscription { | 59 | struct tipc_subscription { |
63 | struct tipc_subscriber *subscriber; | 60 | struct tipc_subscriber *subscriber; |
64 | struct tipc_name_seq seq; | ||
65 | struct net *net; | 61 | struct net *net; |
66 | unsigned long timeout; | ||
67 | u32 filter; | ||
68 | struct timer_list timer; | 62 | struct timer_list timer; |
69 | struct list_head nameseq_list; | 63 | struct list_head nameseq_list; |
70 | struct list_head subscrp_list; | 64 | struct list_head subscrp_list; |
@@ -72,11 +66,14 @@ struct tipc_subscription { | |||
72 | struct tipc_event evt; | 66 | struct tipc_event evt; |
73 | }; | 67 | }; |
74 | 68 | ||
75 | int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, | 69 | int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower, |
76 | u32 found_upper); | 70 | u32 found_upper); |
77 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, | 71 | void tipc_subscrp_report_overlap(struct tipc_subscription *sub, |
78 | u32 found_lower, u32 found_upper, u32 event, | 72 | u32 found_lower, u32 found_upper, u32 event, |
79 | u32 port_ref, u32 node, int must); | 73 | u32 port_ref, u32 node, int must); |
74 | void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, | ||
75 | struct tipc_name_seq *out); | ||
76 | u32 tipc_subscrp_convert_seq_type(u32 type, int swap); | ||
80 | int tipc_topsrv_start(struct net *net); | 77 | int tipc_topsrv_start(struct net *net); |
81 | void tipc_topsrv_stop(struct net *net); | 78 | void tipc_topsrv_stop(struct net *net); |
82 | 79 | ||
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index d63a911e7fe2..c9cf2be3674a 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c | |||
@@ -48,19 +48,12 @@ | |||
48 | #include <linux/tipc_netlink.h> | 48 | #include <linux/tipc_netlink.h> |
49 | #include "core.h" | 49 | #include "core.h" |
50 | #include "bearer.h" | 50 | #include "bearer.h" |
51 | #include "netlink.h" | ||
51 | 52 | ||
52 | /* IANA assigned UDP port */ | 53 | /* IANA assigned UDP port */ |
53 | #define UDP_PORT_DEFAULT 6118 | 54 | #define UDP_PORT_DEFAULT 6118 |
54 | 55 | ||
55 | #define UDP_MIN_HEADROOM 28 | 56 | #define UDP_MIN_HEADROOM 48 |
56 | |||
57 | static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = { | ||
58 | [TIPC_NLA_UDP_UNSPEC] = {.type = NLA_UNSPEC}, | ||
59 | [TIPC_NLA_UDP_LOCAL] = {.type = NLA_BINARY, | ||
60 | .len = sizeof(struct sockaddr_storage)}, | ||
61 | [TIPC_NLA_UDP_REMOTE] = {.type = NLA_BINARY, | ||
62 | .len = sizeof(struct sockaddr_storage)}, | ||
63 | }; | ||
64 | 57 | ||
65 | /** | 58 | /** |
66 | * struct udp_media_addr - IP/UDP addressing information | 59 | * struct udp_media_addr - IP/UDP addressing information |
@@ -181,6 +174,8 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
181 | err = PTR_ERR(rt); | 174 | err = PTR_ERR(rt); |
182 | goto tx_error; | 175 | goto tx_error; |
183 | } | 176 | } |
177 | |||
178 | skb->dev = rt->dst.dev; | ||
184 | ttl = ip4_dst_hoplimit(&rt->dst); | 179 | ttl = ip4_dst_hoplimit(&rt->dst); |
185 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, | 180 | udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, |
186 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, | 181 | dst->ipv4.s_addr, 0, ttl, 0, src->udp_port, |
@@ -201,7 +196,7 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, | |||
201 | ttl = ip6_dst_hoplimit(ndst); | 196 | ttl = ip6_dst_hoplimit(ndst); |
202 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, | 197 | err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, |
203 | ndst->dev, &src->ipv6, | 198 | ndst->dev, &src->ipv6, |
204 | &dst->ipv6, 0, ttl, src->udp_port, | 199 | &dst->ipv6, 0, ttl, 0, src->udp_port, |
205 | dst->udp_port, false); | 200 | dst->udp_port, false); |
206 | #endif | 201 | #endif |
207 | } | 202 | } |
@@ -274,7 +269,7 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub, | |||
274 | struct udp_media_addr *remote) | 269 | struct udp_media_addr *remote) |
275 | { | 270 | { |
276 | struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; | 271 | struct nlattr *opts[TIPC_NLA_UDP_MAX + 1]; |
277 | struct sockaddr_storage *sa_local, *sa_remote; | 272 | struct sockaddr_storage sa_local, sa_remote; |
278 | 273 | ||
279 | if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) | 274 | if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) |
280 | goto err; | 275 | goto err; |
@@ -283,41 +278,48 @@ static int parse_options(struct nlattr *attrs[], struct udp_bearer *ub, | |||
283 | tipc_nl_udp_policy)) | 278 | tipc_nl_udp_policy)) |
284 | goto err; | 279 | goto err; |
285 | if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { | 280 | if (opts[TIPC_NLA_UDP_LOCAL] && opts[TIPC_NLA_UDP_REMOTE]) { |
286 | sa_local = nla_data(opts[TIPC_NLA_UDP_LOCAL]); | 281 | nla_memcpy(&sa_local, opts[TIPC_NLA_UDP_LOCAL], |
287 | sa_remote = nla_data(opts[TIPC_NLA_UDP_REMOTE]); | 282 | sizeof(sa_local)); |
283 | nla_memcpy(&sa_remote, opts[TIPC_NLA_UDP_REMOTE], | ||
284 | sizeof(sa_remote)); | ||
288 | } else { | 285 | } else { |
289 | err: | 286 | err: |
290 | pr_err("Invalid UDP bearer configuration"); | 287 | pr_err("Invalid UDP bearer configuration"); |
291 | return -EINVAL; | 288 | return -EINVAL; |
292 | } | 289 | } |
293 | if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET) { | 290 | if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET) { |
294 | struct sockaddr_in *ip4; | 291 | struct sockaddr_in *ip4; |
295 | 292 | ||
296 | ip4 = (struct sockaddr_in *)sa_local; | 293 | ip4 = (struct sockaddr_in *)&sa_local; |
297 | local->proto = htons(ETH_P_IP); | 294 | local->proto = htons(ETH_P_IP); |
298 | local->udp_port = ip4->sin_port; | 295 | local->udp_port = ip4->sin_port; |
299 | local->ipv4.s_addr = ip4->sin_addr.s_addr; | 296 | local->ipv4.s_addr = ip4->sin_addr.s_addr; |
300 | 297 | ||
301 | ip4 = (struct sockaddr_in *)sa_remote; | 298 | ip4 = (struct sockaddr_in *)&sa_remote; |
302 | remote->proto = htons(ETH_P_IP); | 299 | remote->proto = htons(ETH_P_IP); |
303 | remote->udp_port = ip4->sin_port; | 300 | remote->udp_port = ip4->sin_port; |
304 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; | 301 | remote->ipv4.s_addr = ip4->sin_addr.s_addr; |
305 | return 0; | 302 | return 0; |
306 | 303 | ||
307 | #if IS_ENABLED(CONFIG_IPV6) | 304 | #if IS_ENABLED(CONFIG_IPV6) |
308 | } else if ((sa_local->ss_family & sa_remote->ss_family) == AF_INET6) { | 305 | } else if ((sa_local.ss_family & sa_remote.ss_family) == AF_INET6) { |
306 | int atype; | ||
309 | struct sockaddr_in6 *ip6; | 307 | struct sockaddr_in6 *ip6; |
310 | 308 | ||
311 | ip6 = (struct sockaddr_in6 *)sa_local; | 309 | ip6 = (struct sockaddr_in6 *)&sa_local; |
310 | atype = ipv6_addr_type(&ip6->sin6_addr); | ||
311 | if (__ipv6_addr_needs_scope_id(atype) && !ip6->sin6_scope_id) | ||
312 | return -EINVAL; | ||
313 | |||
312 | local->proto = htons(ETH_P_IPV6); | 314 | local->proto = htons(ETH_P_IPV6); |
313 | local->udp_port = ip6->sin6_port; | 315 | local->udp_port = ip6->sin6_port; |
314 | local->ipv6 = ip6->sin6_addr; | 316 | memcpy(&local->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
315 | ub->ifindex = ip6->sin6_scope_id; | 317 | ub->ifindex = ip6->sin6_scope_id; |
316 | 318 | ||
317 | ip6 = (struct sockaddr_in6 *)sa_remote; | 319 | ip6 = (struct sockaddr_in6 *)&sa_remote; |
318 | remote->proto = htons(ETH_P_IPV6); | 320 | remote->proto = htons(ETH_P_IPV6); |
319 | remote->udp_port = ip6->sin6_port; | 321 | remote->udp_port = ip6->sin6_port; |
320 | remote->ipv6 = ip6->sin6_addr; | 322 | memcpy(&remote->ipv6, &ip6->sin6_addr, sizeof(struct in6_addr)); |
321 | return 0; | 323 | return 0; |
322 | #endif | 324 | #endif |
323 | } | 325 | } |