~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/qrtr/ns.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2 /*
  3  * Copyright (c) 2015, Sony Mobile Communications Inc.
  4  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
  5  * Copyright (c) 2020, Linaro Ltd.
  6  */
  7 
  8 #include <linux/module.h>
  9 #include <linux/qrtr.h>
 10 #include <linux/workqueue.h>
 11 #include <net/sock.h>
 12 
 13 #include "qrtr.h"
 14 
 15 #include <trace/events/sock.h>
 16 #define CREATE_TRACE_POINTS
 17 #include <trace/events/qrtr.h>
 18 
 19 static DEFINE_XARRAY(nodes);
 20 
 21 static struct {
 22         struct socket *sock;
 23         struct sockaddr_qrtr bcast_sq;
 24         struct list_head lookups;
 25         struct workqueue_struct *workqueue;
 26         struct work_struct work;
 27         int local_node;
 28 } qrtr_ns;
 29 
 30 static const char * const qrtr_ctrl_pkt_strings[] = {
 31         [QRTR_TYPE_HELLO]       = "hello",
 32         [QRTR_TYPE_BYE]         = "bye",
 33         [QRTR_TYPE_NEW_SERVER]  = "new-server",
 34         [QRTR_TYPE_DEL_SERVER]  = "del-server",
 35         [QRTR_TYPE_DEL_CLIENT]  = "del-client",
 36         [QRTR_TYPE_RESUME_TX]   = "resume-tx",
 37         [QRTR_TYPE_EXIT]        = "exit",
 38         [QRTR_TYPE_PING]        = "ping",
 39         [QRTR_TYPE_NEW_LOOKUP]  = "new-lookup",
 40         [QRTR_TYPE_DEL_LOOKUP]  = "del-lookup",
 41 };
 42 
 43 struct qrtr_server_filter {
 44         unsigned int service;
 45         unsigned int instance;
 46         unsigned int ifilter;
 47 };
 48 
 49 struct qrtr_lookup {
 50         unsigned int service;
 51         unsigned int instance;
 52 
 53         struct sockaddr_qrtr sq;
 54         struct list_head li;
 55 };
 56 
 57 struct qrtr_server {
 58         unsigned int service;
 59         unsigned int instance;
 60 
 61         unsigned int node;
 62         unsigned int port;
 63 
 64         struct list_head qli;
 65 };
 66 
 67 struct qrtr_node {
 68         unsigned int id;
 69         struct xarray servers;
 70 };
 71 
 72 static struct qrtr_node *node_get(unsigned int node_id)
 73 {
 74         struct qrtr_node *node;
 75 
 76         node = xa_load(&nodes, node_id);
 77         if (node)
 78                 return node;
 79 
 80         /* If node didn't exist, allocate and insert it to the tree */
 81         node = kzalloc(sizeof(*node), GFP_KERNEL);
 82         if (!node)
 83                 return NULL;
 84 
 85         node->id = node_id;
 86         xa_init(&node->servers);
 87 
 88         if (xa_store(&nodes, node_id, node, GFP_KERNEL)) {
 89                 kfree(node);
 90                 return NULL;
 91         }
 92 
 93         return node;
 94 }
 95 
 96 static int server_match(const struct qrtr_server *srv,
 97                         const struct qrtr_server_filter *f)
 98 {
 99         unsigned int ifilter = f->ifilter;
100 
101         if (f->service != 0 && srv->service != f->service)
102                 return 0;
103         if (!ifilter && f->instance)
104                 ifilter = ~0;
105 
106         return (srv->instance & ifilter) == f->instance;
107 }
108 
109 static int service_announce_new(struct sockaddr_qrtr *dest,
110                                 struct qrtr_server *srv)
111 {
112         struct qrtr_ctrl_pkt pkt;
113         struct msghdr msg = { };
114         struct kvec iv;
115 
116         trace_qrtr_ns_service_announce_new(srv->service, srv->instance,
117                                            srv->node, srv->port);
118 
119         iv.iov_base = &pkt;
120         iv.iov_len = sizeof(pkt);
121 
122         memset(&pkt, 0, sizeof(pkt));
123         pkt.cmd = cpu_to_le32(QRTR_TYPE_NEW_SERVER);
124         pkt.server.service = cpu_to_le32(srv->service);
125         pkt.server.instance = cpu_to_le32(srv->instance);
126         pkt.server.node = cpu_to_le32(srv->node);
127         pkt.server.port = cpu_to_le32(srv->port);
128 
129         msg.msg_name = (struct sockaddr *)dest;
130         msg.msg_namelen = sizeof(*dest);
131 
132         return kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
133 }
134 
135 static void service_announce_del(struct sockaddr_qrtr *dest,
136                                  struct qrtr_server *srv)
137 {
138         struct qrtr_ctrl_pkt pkt;
139         struct msghdr msg = { };
140         struct kvec iv;
141         int ret;
142 
143         trace_qrtr_ns_service_announce_del(srv->service, srv->instance,
144                                            srv->node, srv->port);
145 
146         iv.iov_base = &pkt;
147         iv.iov_len = sizeof(pkt);
148 
149         memset(&pkt, 0, sizeof(pkt));
150         pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER);
151         pkt.server.service = cpu_to_le32(srv->service);
152         pkt.server.instance = cpu_to_le32(srv->instance);
153         pkt.server.node = cpu_to_le32(srv->node);
154         pkt.server.port = cpu_to_le32(srv->port);
155 
156         msg.msg_name = (struct sockaddr *)dest;
157         msg.msg_namelen = sizeof(*dest);
158 
159         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
160         if (ret < 0 && ret != -ENODEV)
161                 pr_err("failed to announce del service\n");
162 
163         return;
164 }
165 
166 static void lookup_notify(struct sockaddr_qrtr *to, struct qrtr_server *srv,
167                           bool new)
168 {
169         struct qrtr_ctrl_pkt pkt;
170         struct msghdr msg = { };
171         struct kvec iv;
172         int ret;
173 
174         iv.iov_base = &pkt;
175         iv.iov_len = sizeof(pkt);
176 
177         memset(&pkt, 0, sizeof(pkt));
178         pkt.cmd = new ? cpu_to_le32(QRTR_TYPE_NEW_SERVER) :
179                         cpu_to_le32(QRTR_TYPE_DEL_SERVER);
180         if (srv) {
181                 pkt.server.service = cpu_to_le32(srv->service);
182                 pkt.server.instance = cpu_to_le32(srv->instance);
183                 pkt.server.node = cpu_to_le32(srv->node);
184                 pkt.server.port = cpu_to_le32(srv->port);
185         }
186 
187         msg.msg_name = (struct sockaddr *)to;
188         msg.msg_namelen = sizeof(*to);
189 
190         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
191         if (ret < 0 && ret != -ENODEV)
192                 pr_err("failed to send lookup notification\n");
193 }
194 
195 static int announce_servers(struct sockaddr_qrtr *sq)
196 {
197         struct qrtr_server *srv;
198         struct qrtr_node *node;
199         unsigned long index;
200         int ret;
201 
202         node = node_get(qrtr_ns.local_node);
203         if (!node)
204                 return 0;
205 
206         /* Announce the list of servers registered in this node */
207         xa_for_each(&node->servers, index, srv) {
208                 ret = service_announce_new(sq, srv);
209                 if (ret < 0) {
210                         if (ret == -ENODEV)
211                                 continue;
212 
213                         pr_err("failed to announce new service\n");
214                         return ret;
215                 }
216         }
217         return 0;
218 }
219 
220 static struct qrtr_server *server_add(unsigned int service,
221                                       unsigned int instance,
222                                       unsigned int node_id,
223                                       unsigned int port)
224 {
225         struct qrtr_server *srv;
226         struct qrtr_server *old;
227         struct qrtr_node *node;
228 
229         if (!service || !port)
230                 return NULL;
231 
232         srv = kzalloc(sizeof(*srv), GFP_KERNEL);
233         if (!srv)
234                 return NULL;
235 
236         srv->service = service;
237         srv->instance = instance;
238         srv->node = node_id;
239         srv->port = port;
240 
241         node = node_get(node_id);
242         if (!node)
243                 goto err;
244 
245         /* Delete the old server on the same port */
246         old = xa_store(&node->servers, port, srv, GFP_KERNEL);
247         if (old) {
248                 if (xa_is_err(old)) {
249                         pr_err("failed to add server [0x%x:0x%x] ret:%d\n",
250                                srv->service, srv->instance, xa_err(old));
251                         goto err;
252                 } else {
253                         kfree(old);
254                 }
255         }
256 
257         trace_qrtr_ns_server_add(srv->service, srv->instance,
258                                  srv->node, srv->port);
259 
260         return srv;
261 
262 err:
263         kfree(srv);
264         return NULL;
265 }
266 
267 static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
268 {
269         struct qrtr_lookup *lookup;
270         struct qrtr_server *srv;
271         struct list_head *li;
272 
273         srv = xa_load(&node->servers, port);
274         if (!srv)
275                 return -ENOENT;
276 
277         xa_erase(&node->servers, port);
278 
279         /* Broadcast the removal of local servers */
280         if (srv->node == qrtr_ns.local_node && bcast)
281                 service_announce_del(&qrtr_ns.bcast_sq, srv);
282 
283         /* Announce the service's disappearance to observers */
284         list_for_each(li, &qrtr_ns.lookups) {
285                 lookup = container_of(li, struct qrtr_lookup, li);
286                 if (lookup->service && lookup->service != srv->service)
287                         continue;
288                 if (lookup->instance && lookup->instance != srv->instance)
289                         continue;
290 
291                 lookup_notify(&lookup->sq, srv, false);
292         }
293 
294         kfree(srv);
295 
296         return 0;
297 }
298 
299 static int say_hello(struct sockaddr_qrtr *dest)
300 {
301         struct qrtr_ctrl_pkt pkt;
302         struct msghdr msg = { };
303         struct kvec iv;
304         int ret;
305 
306         iv.iov_base = &pkt;
307         iv.iov_len = sizeof(pkt);
308 
309         memset(&pkt, 0, sizeof(pkt));
310         pkt.cmd = cpu_to_le32(QRTR_TYPE_HELLO);
311 
312         msg.msg_name = (struct sockaddr *)dest;
313         msg.msg_namelen = sizeof(*dest);
314 
315         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
316         if (ret < 0)
317                 pr_err("failed to send hello msg\n");
318 
319         return ret;
320 }
321 
322 /* Announce the list of servers registered on the local node */
323 static int ctrl_cmd_hello(struct sockaddr_qrtr *sq)
324 {
325         int ret;
326 
327         ret = say_hello(sq);
328         if (ret < 0)
329                 return ret;
330 
331         return announce_servers(sq);
332 }
333 
334 static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
335 {
336         struct qrtr_node *local_node;
337         struct qrtr_ctrl_pkt pkt;
338         struct qrtr_server *srv;
339         struct sockaddr_qrtr sq;
340         struct msghdr msg = { };
341         struct qrtr_node *node;
342         unsigned long index;
343         struct kvec iv;
344         int ret;
345 
346         iv.iov_base = &pkt;
347         iv.iov_len = sizeof(pkt);
348 
349         node = node_get(from->sq_node);
350         if (!node)
351                 return 0;
352 
353         /* Advertise removal of this client to all servers of remote node */
354         xa_for_each(&node->servers, index, srv)
355                 server_del(node, srv->port, true);
356 
357         /* Advertise the removal of this client to all local servers */
358         local_node = node_get(qrtr_ns.local_node);
359         if (!local_node)
360                 return 0;
361 
362         memset(&pkt, 0, sizeof(pkt));
363         pkt.cmd = cpu_to_le32(QRTR_TYPE_BYE);
364         pkt.client.node = cpu_to_le32(from->sq_node);
365 
366         xa_for_each(&local_node->servers, index, srv) {
367                 sq.sq_family = AF_QIPCRTR;
368                 sq.sq_node = srv->node;
369                 sq.sq_port = srv->port;
370 
371                 msg.msg_name = (struct sockaddr *)&sq;
372                 msg.msg_namelen = sizeof(sq);
373 
374                 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
375                 if (ret < 0 && ret != -ENODEV) {
376                         pr_err("failed to send bye cmd\n");
377                         return ret;
378                 }
379         }
380         return 0;
381 }
382 
383 static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
384                                unsigned int node_id, unsigned int port)
385 {
386         struct qrtr_node *local_node;
387         struct qrtr_lookup *lookup;
388         struct qrtr_ctrl_pkt pkt;
389         struct msghdr msg = { };
390         struct qrtr_server *srv;
391         struct sockaddr_qrtr sq;
392         struct qrtr_node *node;
393         struct list_head *tmp;
394         struct list_head *li;
395         unsigned long index;
396         struct kvec iv;
397         int ret;
398 
399         iv.iov_base = &pkt;
400         iv.iov_len = sizeof(pkt);
401 
402         /* Don't accept spoofed messages */
403         if (from->sq_node != node_id)
404                 return -EINVAL;
405 
406         /* Local DEL_CLIENT messages comes from the port being closed */
407         if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
408                 return -EINVAL;
409 
410         /* Remove any lookups by this client */
411         list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
412                 lookup = container_of(li, struct qrtr_lookup, li);
413                 if (lookup->sq.sq_node != node_id)
414                         continue;
415                 if (lookup->sq.sq_port != port)
416                         continue;
417 
418                 list_del(&lookup->li);
419                 kfree(lookup);
420         }
421 
422         /* Remove the server belonging to this port but don't broadcast
423          * DEL_SERVER. Neighbours would've already removed the server belonging
424          * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
425          */
426         node = node_get(node_id);
427         if (node)
428                 server_del(node, port, false);
429 
430         /* Advertise the removal of this client to all local servers */
431         local_node = node_get(qrtr_ns.local_node);
432         if (!local_node)
433                 return 0;
434 
435         memset(&pkt, 0, sizeof(pkt));
436         pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
437         pkt.client.node = cpu_to_le32(node_id);
438         pkt.client.port = cpu_to_le32(port);
439 
440         xa_for_each(&local_node->servers, index, srv) {
441                 sq.sq_family = AF_QIPCRTR;
442                 sq.sq_node = srv->node;
443                 sq.sq_port = srv->port;
444 
445                 msg.msg_name = (struct sockaddr *)&sq;
446                 msg.msg_namelen = sizeof(sq);
447 
448                 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
449                 if (ret < 0 && ret != -ENODEV) {
450                         pr_err("failed to send del client cmd\n");
451                         return ret;
452                 }
453         }
454         return 0;
455 }
456 
457 static int ctrl_cmd_new_server(struct sockaddr_qrtr *from,
458                                unsigned int service, unsigned int instance,
459                                unsigned int node_id, unsigned int port)
460 {
461         struct qrtr_lookup *lookup;
462         struct qrtr_server *srv;
463         struct list_head *li;
464         int ret = 0;
465 
466         /* Ignore specified node and port for local servers */
467         if (from->sq_node == qrtr_ns.local_node) {
468                 node_id = from->sq_node;
469                 port = from->sq_port;
470         }
471 
472         srv = server_add(service, instance, node_id, port);
473         if (!srv)
474                 return -EINVAL;
475 
476         if (srv->node == qrtr_ns.local_node) {
477                 ret = service_announce_new(&qrtr_ns.bcast_sq, srv);
478                 if (ret < 0) {
479                         pr_err("failed to announce new service\n");
480                         return ret;
481                 }
482         }
483 
484         /* Notify any potential lookups about the new server */
485         list_for_each(li, &qrtr_ns.lookups) {
486                 lookup = container_of(li, struct qrtr_lookup, li);
487                 if (lookup->service && lookup->service != service)
488                         continue;
489                 if (lookup->instance && lookup->instance != instance)
490                         continue;
491 
492                 lookup_notify(&lookup->sq, srv, true);
493         }
494 
495         return ret;
496 }
497 
498 static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
499                                unsigned int service, unsigned int instance,
500                                unsigned int node_id, unsigned int port)
501 {
502         struct qrtr_node *node;
503 
504         /* Ignore specified node and port for local servers*/
505         if (from->sq_node == qrtr_ns.local_node) {
506                 node_id = from->sq_node;
507                 port = from->sq_port;
508         }
509 
510         /* Local servers may only unregister themselves */
511         if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
512                 return -EINVAL;
513 
514         node = node_get(node_id);
515         if (!node)
516                 return -ENOENT;
517 
518         server_del(node, port, true);
519 
520         return 0;
521 }
522 
523 static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
524                                unsigned int service, unsigned int instance)
525 {
526         struct qrtr_server_filter filter;
527         struct qrtr_lookup *lookup;
528         struct qrtr_server *srv;
529         struct qrtr_node *node;
530         unsigned long node_idx;
531         unsigned long srv_idx;
532 
533         /* Accept only local observers */
534         if (from->sq_node != qrtr_ns.local_node)
535                 return -EINVAL;
536 
537         lookup = kzalloc(sizeof(*lookup), GFP_KERNEL);
538         if (!lookup)
539                 return -ENOMEM;
540 
541         lookup->sq = *from;
542         lookup->service = service;
543         lookup->instance = instance;
544         list_add_tail(&lookup->li, &qrtr_ns.lookups);
545 
546         memset(&filter, 0, sizeof(filter));
547         filter.service = service;
548         filter.instance = instance;
549 
550         xa_for_each(&nodes, node_idx, node) {
551                 xa_for_each(&node->servers, srv_idx, srv) {
552                         if (!server_match(srv, &filter))
553                                 continue;
554 
555                         lookup_notify(from, srv, true);
556                 }
557         }
558 
559         /* Empty notification, to indicate end of listing */
560         lookup_notify(from, NULL, true);
561 
562         return 0;
563 }
564 
565 static void ctrl_cmd_del_lookup(struct sockaddr_qrtr *from,
566                                 unsigned int service, unsigned int instance)
567 {
568         struct qrtr_lookup *lookup;
569         struct list_head *tmp;
570         struct list_head *li;
571 
572         list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
573                 lookup = container_of(li, struct qrtr_lookup, li);
574                 if (lookup->sq.sq_node != from->sq_node)
575                         continue;
576                 if (lookup->sq.sq_port != from->sq_port)
577                         continue;
578                 if (lookup->service != service)
579                         continue;
580                 if (lookup->instance && lookup->instance != instance)
581                         continue;
582 
583                 list_del(&lookup->li);
584                 kfree(lookup);
585         }
586 }
587 
588 static void qrtr_ns_worker(struct work_struct *work)
589 {
590         const struct qrtr_ctrl_pkt *pkt;
591         size_t recv_buf_size = 4096;
592         struct sockaddr_qrtr sq;
593         struct msghdr msg = { };
594         unsigned int cmd;
595         ssize_t msglen;
596         void *recv_buf;
597         struct kvec iv;
598         int ret;
599 
600         msg.msg_name = (struct sockaddr *)&sq;
601         msg.msg_namelen = sizeof(sq);
602 
603         recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
604         if (!recv_buf)
605                 return;
606 
607         for (;;) {
608                 iv.iov_base = recv_buf;
609                 iv.iov_len = recv_buf_size;
610 
611                 msglen = kernel_recvmsg(qrtr_ns.sock, &msg, &iv, 1,
612                                         iv.iov_len, MSG_DONTWAIT);
613 
614                 if (msglen == -EAGAIN)
615                         break;
616 
617                 if (msglen < 0) {
618                         pr_err("error receiving packet: %zd\n", msglen);
619                         break;
620                 }
621 
622                 pkt = recv_buf;
623                 cmd = le32_to_cpu(pkt->cmd);
624                 if (cmd < ARRAY_SIZE(qrtr_ctrl_pkt_strings) &&
625                     qrtr_ctrl_pkt_strings[cmd])
626                         trace_qrtr_ns_message(qrtr_ctrl_pkt_strings[cmd],
627                                               sq.sq_node, sq.sq_port);
628 
629                 ret = 0;
630                 switch (cmd) {
631                 case QRTR_TYPE_HELLO:
632                         ret = ctrl_cmd_hello(&sq);
633                         break;
634                 case QRTR_TYPE_BYE:
635                         ret = ctrl_cmd_bye(&sq);
636                         break;
637                 case QRTR_TYPE_DEL_CLIENT:
638                         ret = ctrl_cmd_del_client(&sq,
639                                         le32_to_cpu(pkt->client.node),
640                                         le32_to_cpu(pkt->client.port));
641                         break;
642                 case QRTR_TYPE_NEW_SERVER:
643                         ret = ctrl_cmd_new_server(&sq,
644                                         le32_to_cpu(pkt->server.service),
645                                         le32_to_cpu(pkt->server.instance),
646                                         le32_to_cpu(pkt->server.node),
647                                         le32_to_cpu(pkt->server.port));
648                         break;
649                 case QRTR_TYPE_DEL_SERVER:
650                         ret = ctrl_cmd_del_server(&sq,
651                                          le32_to_cpu(pkt->server.service),
652                                          le32_to_cpu(pkt->server.instance),
653                                          le32_to_cpu(pkt->server.node),
654                                          le32_to_cpu(pkt->server.port));
655                         break;
656                 case QRTR_TYPE_EXIT:
657                 case QRTR_TYPE_PING:
658                 case QRTR_TYPE_RESUME_TX:
659                         break;
660                 case QRTR_TYPE_NEW_LOOKUP:
661                         ret = ctrl_cmd_new_lookup(&sq,
662                                          le32_to_cpu(pkt->server.service),
663                                          le32_to_cpu(pkt->server.instance));
664                         break;
665                 case QRTR_TYPE_DEL_LOOKUP:
666                         ctrl_cmd_del_lookup(&sq,
667                                     le32_to_cpu(pkt->server.service),
668                                     le32_to_cpu(pkt->server.instance));
669                         break;
670                 }
671 
672                 if (ret < 0)
673                         pr_err("failed while handling packet from %d:%d",
674                                sq.sq_node, sq.sq_port);
675         }
676 
677         kfree(recv_buf);
678 }
679 
680 static void qrtr_ns_data_ready(struct sock *sk)
681 {
682         trace_sk_data_ready(sk);
683 
684         queue_work(qrtr_ns.workqueue, &qrtr_ns.work);
685 }
686 
687 int qrtr_ns_init(void)
688 {
689         struct sockaddr_qrtr sq;
690         int ret;
691 
692         INIT_LIST_HEAD(&qrtr_ns.lookups);
693         INIT_WORK(&qrtr_ns.work, qrtr_ns_worker);
694 
695         ret = sock_create_kern(&init_net, AF_QIPCRTR, SOCK_DGRAM,
696                                PF_QIPCRTR, &qrtr_ns.sock);
697         if (ret < 0)
698                 return ret;
699 
700         ret = kernel_getsockname(qrtr_ns.sock, (struct sockaddr *)&sq);
701         if (ret < 0) {
702                 pr_err("failed to get socket name\n");
703                 goto err_sock;
704         }
705 
706         qrtr_ns.workqueue = alloc_ordered_workqueue("qrtr_ns_handler", 0);
707         if (!qrtr_ns.workqueue) {
708                 ret = -ENOMEM;
709                 goto err_sock;
710         }
711 
712         qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready;
713 
714         sq.sq_port = QRTR_PORT_CTRL;
715         qrtr_ns.local_node = sq.sq_node;
716 
717         ret = kernel_bind(qrtr_ns.sock, (struct sockaddr *)&sq, sizeof(sq));
718         if (ret < 0) {
719                 pr_err("failed to bind to socket\n");
720                 goto err_wq;
721         }
722 
723         qrtr_ns.bcast_sq.sq_family = AF_QIPCRTR;
724         qrtr_ns.bcast_sq.sq_node = QRTR_NODE_BCAST;
725         qrtr_ns.bcast_sq.sq_port = QRTR_PORT_CTRL;
726 
727         ret = say_hello(&qrtr_ns.bcast_sq);
728         if (ret < 0)
729                 goto err_wq;
730 
731         /* As the qrtr ns socket owner and creator is the same module, we have
732          * to decrease the qrtr module reference count to guarantee that it
733          * remains zero after the ns socket is created, otherwise, executing
734          * "rmmod" command is unable to make the qrtr module deleted after the
735          *  qrtr module is inserted successfully.
736          *
737          * However, the reference count is increased twice in
738          * sock_create_kern(): one is to increase the reference count of owner
739          * of qrtr socket's proto_ops struct; another is to increment the
740          * reference count of owner of qrtr proto struct. Therefore, we must
741          * decrement the module reference count twice to ensure that it keeps
742          * zero after server's listening socket is created. Of course, we
743          * must bump the module reference count twice as well before the socket
744          * is closed.
745          */
746         module_put(qrtr_ns.sock->ops->owner);
747         module_put(qrtr_ns.sock->sk->sk_prot_creator->owner);
748 
749         return 0;
750 
751 err_wq:
752         destroy_workqueue(qrtr_ns.workqueue);
753 err_sock:
754         sock_release(qrtr_ns.sock);
755         return ret;
756 }
757 EXPORT_SYMBOL_GPL(qrtr_ns_init);
758 
759 void qrtr_ns_remove(void)
760 {
761         cancel_work_sync(&qrtr_ns.work);
762         destroy_workqueue(qrtr_ns.workqueue);
763 
764         /* sock_release() expects the two references that were put during
765          * qrtr_ns_init(). This function is only called during module remove,
766          * so try_stop_module() has already set the refcnt to 0. Use
767          * __module_get() instead of try_module_get() to successfully take two
768          * references.
769          */
770         __module_get(qrtr_ns.sock->ops->owner);
771         __module_get(qrtr_ns.sock->sk->sk_prot_creator->owner);
772         sock_release(qrtr_ns.sock);
773 }
774 EXPORT_SYMBOL_GPL(qrtr_ns_remove);
775 
776 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
777 MODULE_DESCRIPTION("Qualcomm IPC Router Nameservice");
778 MODULE_LICENSE("Dual BSD/GPL");
779 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php