]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/ofed/drivers/infiniband/core/ib_addr.c
Upgrade to OpenSSH 7.9p1.
[FreeBSD/FreeBSD.git] / sys / ofed / drivers / infiniband / core / ib_addr.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3  *
4  * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
5  * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
6  * Copyright (c) 1999-2019, Mellanox Technologies, Inc. All rights reserved.
7  * Copyright (c) 2005 Intel Corporation.  All rights reserved.
8  *
9  * This software is available to you under a choice of one of two
10  * licenses.  You may choose to be licensed under the terms of the GNU
11  * General Public License (GPL) Version 2, available from the file
12  * COPYING in the main directory of this source tree, or the
13  * OpenIB.org BSD license below:
14  *
15  *     Redistribution and use in source and binary forms, with or
16  *     without modification, are permitted provided that the following
17  *     conditions are met:
18  *
19  *      - Redistributions of source code must retain the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer.
22  *
23  *      - Redistributions in binary form must reproduce the above
24  *        copyright notice, this list of conditions and the following
25  *        disclaimer in the documentation and/or other materials
26  *        provided with the distribution.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35  * SOFTWARE.
36  */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <linux/mutex.h>
42 #include <linux/inetdevice.h>
43 #include <linux/slab.h>
44 #include <linux/workqueue.h>
45 #include <linux/module.h>
46 #include <net/route.h>
47 #include <net/netevent.h>
48 #include <rdma/ib_addr.h>
49 #include <rdma/ib.h>
50
51 #include <netinet/if_ether.h>
52 #include <netinet/ip_var.h>
53 #include <netinet6/scope6_var.h>
54 #include <netinet6/in6_pcb.h>
55
56 #include "core_priv.h"
57
58 struct addr_req {
59         struct list_head list;
60         struct sockaddr_storage src_addr;
61         struct sockaddr_storage dst_addr;
62         struct rdma_dev_addr *addr;
63         struct rdma_addr_client *client;
64         void *context;
65         void (*callback)(int status, struct sockaddr *src_addr,
66                          struct rdma_dev_addr *addr, void *context);
67         int timeout;
68         int status;
69 };
70
71 static void process_req(struct work_struct *work);
72
73 static DEFINE_MUTEX(lock);
74 static LIST_HEAD(req_list);
75 static DECLARE_DELAYED_WORK(work, process_req);
76 static struct workqueue_struct *addr_wq;
77
78 int rdma_addr_size(struct sockaddr *addr)
79 {
80         switch (addr->sa_family) {
81         case AF_INET:
82                 return sizeof(struct sockaddr_in);
83         case AF_INET6:
84                 return sizeof(struct sockaddr_in6);
85         case AF_IB:
86                 return sizeof(struct sockaddr_ib);
87         default:
88                 return 0;
89         }
90 }
91 EXPORT_SYMBOL(rdma_addr_size);
92
93 int rdma_addr_size_in6(struct sockaddr_in6 *addr)
94 {
95         int ret = rdma_addr_size((struct sockaddr *) addr);
96
97         return ret <= sizeof(*addr) ? ret : 0;
98 }
99 EXPORT_SYMBOL(rdma_addr_size_in6);
100
101 int rdma_addr_size_kss(struct sockaddr_storage *addr)
102 {
103         int ret = rdma_addr_size((struct sockaddr *) addr);
104
105         return ret <= sizeof(*addr) ? ret : 0;
106 }
107 EXPORT_SYMBOL(rdma_addr_size_kss);
108
109 static struct rdma_addr_client self;
110
111 void rdma_addr_register_client(struct rdma_addr_client *client)
112 {
113         atomic_set(&client->refcount, 1);
114         init_completion(&client->comp);
115 }
116 EXPORT_SYMBOL(rdma_addr_register_client);
117
118 static inline void put_client(struct rdma_addr_client *client)
119 {
120         if (atomic_dec_and_test(&client->refcount))
121                 complete(&client->comp);
122 }
123
124 void rdma_addr_unregister_client(struct rdma_addr_client *client)
125 {
126         put_client(client);
127         wait_for_completion(&client->comp);
128 }
129 EXPORT_SYMBOL(rdma_addr_unregister_client);
130
131 static inline void
132 rdma_copy_addr_sub(u8 *dst, const u8 *src, unsigned min, unsigned max)
133 {
134         if (min > max)
135                 min = max;
136         memcpy(dst, src, min);
137         memset(dst + min, 0, max - min);
138 }
139
140 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
141                      const unsigned char *dst_dev_addr)
142 {
143         /* check for loopback device */
144         if (dev->if_flags & IFF_LOOPBACK) {
145                 dev_addr->dev_type = ARPHRD_ETHER;
146                 memset(dev_addr->src_dev_addr, 0, MAX_ADDR_LEN);
147                 memset(dev_addr->broadcast, 0, MAX_ADDR_LEN);
148                 memset(dev_addr->dst_dev_addr, 0, MAX_ADDR_LEN);
149                 dev_addr->bound_dev_if = dev->if_index;
150                 return (0);
151         } else if (dev->if_type == IFT_INFINIBAND)
152                 dev_addr->dev_type = ARPHRD_INFINIBAND;
153         else if (dev->if_type == IFT_ETHER)
154                 dev_addr->dev_type = ARPHRD_ETHER;
155         else
156                 dev_addr->dev_type = 0;
157         rdma_copy_addr_sub(dev_addr->src_dev_addr, IF_LLADDR(dev),
158                            dev->if_addrlen, MAX_ADDR_LEN);
159         rdma_copy_addr_sub(dev_addr->broadcast, dev->if_broadcastaddr,
160                            dev->if_addrlen, MAX_ADDR_LEN);
161         if (dst_dev_addr != NULL) {
162                 rdma_copy_addr_sub(dev_addr->dst_dev_addr, dst_dev_addr,
163                                    dev->if_addrlen, MAX_ADDR_LEN);
164         }
165         dev_addr->bound_dev_if = dev->if_index;
166         return 0;
167 }
168 EXPORT_SYMBOL(rdma_copy_addr);
169
170 int rdma_translate_ip(const struct sockaddr *addr,
171                       struct rdma_dev_addr *dev_addr)
172 {
173         struct net_device *dev;
174         int ret;
175
176         if (dev_addr->bound_dev_if) {
177                 dev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
178         } else switch (addr->sa_family) {
179 #ifdef INET
180         case AF_INET:
181                 dev = ip_dev_find(dev_addr->net,
182                         ((const struct sockaddr_in *)addr)->sin_addr.s_addr);
183                 break;
184 #endif
185 #ifdef INET6
186         case AF_INET6:
187                 dev = ip6_dev_find(dev_addr->net,
188                         ((const struct sockaddr_in6 *)addr)->sin6_addr, 0);
189                 break;
190 #endif
191         default:
192                 dev = NULL;
193                 break;
194         }
195
196         if (dev != NULL) {
197                 /* disallow connections through 127.0.0.1 itself */
198                 if (dev->if_flags & IFF_LOOPBACK)
199                         ret = -EINVAL;
200                 else
201                         ret = rdma_copy_addr(dev_addr, dev, NULL);
202                 dev_put(dev);
203         } else {
204                 ret = -ENODEV;
205         }
206         return ret;
207 }
208 EXPORT_SYMBOL(rdma_translate_ip);
209
210 static void set_timeout(int time)
211 {
212         int delay;      /* under FreeBSD ticks are 32-bit */
213
214         delay = time - jiffies;
215         if (delay <= 0)
216                 delay = 1;
217         else if (delay > hz)
218                 delay = hz;
219
220         mod_delayed_work(addr_wq, &work, delay);
221 }
222
223 static void queue_req(struct addr_req *req)
224 {
225         struct addr_req *temp_req;
226
227         mutex_lock(&lock);
228         list_for_each_entry_reverse(temp_req, &req_list, list) {
229                 if (time_after_eq(req->timeout, temp_req->timeout))
230                         break;
231         }
232
233         list_add(&req->list, &temp_req->list);
234
235         if (req_list.next == &req->list)
236                 set_timeout(req->timeout);
237         mutex_unlock(&lock);
238 }
239
240 #if defined(INET) || defined(INET6)
241 static int addr_resolve_multi(u8 *edst, struct ifnet *ifp, struct sockaddr *dst_in)
242 {
243         struct sockaddr *llsa;
244         struct sockaddr_dl sdl;
245         int error;
246
247         sdl.sdl_len = sizeof(sdl);
248         llsa = (struct sockaddr *)&sdl;
249
250         if (ifp->if_resolvemulti == NULL) {
251                 error = EOPNOTSUPP;
252         } else {
253                 error = ifp->if_resolvemulti(ifp, &llsa, dst_in);
254                 if (error == 0) {
255                         rdma_copy_addr_sub(edst, LLADDR((struct sockaddr_dl *)llsa),
256                             ifp->if_addrlen, MAX_ADDR_LEN);
257                 }
258         }
259         return (error);
260 }
261 #endif
262
263 #ifdef INET
264 static int addr4_resolve(struct sockaddr_in *src_in,
265                          const struct sockaddr_in *dst_in,
266                          struct rdma_dev_addr *addr,
267                          u8 *edst,
268                          struct ifnet **ifpp)
269 {
270         enum {
271                 ADDR_VALID = 0,
272                 ADDR_SRC_ANY = 1,
273                 ADDR_DST_ANY = 2,
274         };
275         struct sockaddr_in dst_tmp = *dst_in;
276         in_port_t src_port;
277         struct sockaddr *saddr = NULL;
278         struct rtentry *rte;
279         struct ifnet *ifp;
280         int error;
281         int type;
282
283         /* set VNET, if any */
284         CURVNET_SET(addr->net);
285
286         /* set default TTL limit */
287         addr->hoplimit = V_ip_defttl;
288
289         type = ADDR_VALID;
290         if (src_in->sin_addr.s_addr == INADDR_ANY)
291                 type |= ADDR_SRC_ANY;
292         if (dst_tmp.sin_addr.s_addr == INADDR_ANY)
293                 type |= ADDR_DST_ANY;
294
295         /*
296          * Make sure the socket address length field
297          * is set, else rtalloc1() will fail.
298          */
299         dst_tmp.sin_len = sizeof(dst_tmp);
300
301         /* Step 1 - lookup destination route if any */
302         switch (type) {
303         case ADDR_VALID:
304         case ADDR_SRC_ANY:
305                 /* regular destination route lookup */
306                 rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
307                 if (rte == NULL) {
308                         error = EHOSTUNREACH;
309                         goto done;
310                 } else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
311                         RTFREE_LOCKED(rte);
312                         error = EHOSTUNREACH;
313                         goto done;
314                 }
315                 RT_UNLOCK(rte);
316                 break;
317         default:
318                 error = ENETUNREACH;
319                 goto done;
320         }
321
322         /* Step 2 - find outgoing network interface */
323         switch (type) {
324         case ADDR_VALID:
325                 /* get source interface */
326                 if (addr->bound_dev_if != 0) {
327                         ifp = dev_get_by_index(addr->net, addr->bound_dev_if);
328                 } else {
329                         ifp = ip_dev_find(addr->net, src_in->sin_addr.s_addr);
330                 }
331
332                 /* check source interface */
333                 if (ifp == NULL) {
334                         error = ENETUNREACH;
335                         goto error_rt_free;
336                 } else if (ifp->if_flags & IFF_LOOPBACK) {
337                         /*
338                          * Source address cannot be a loopback device.
339                          */
340                         error = EHOSTUNREACH;
341                         goto error_put_ifp;
342                 } else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
343                         if (memcmp(&src_in->sin_addr, &dst_in->sin_addr,
344                             sizeof(src_in->sin_addr))) {
345                                 /*
346                                  * Destination is loopback, but source
347                                  * and destination address is not the
348                                  * same.
349                                  */
350                                 error = EHOSTUNREACH;
351                                 goto error_put_ifp;
352                         }
353                         /* get destination network interface from route */
354                         dev_put(ifp);
355                         ifp = rte->rt_ifp;
356                         dev_hold(ifp);
357                 } else if (ifp != rte->rt_ifp) {
358                         /*
359                          * Source and destination interfaces are
360                          * different.
361                          */
362                         error = ENETUNREACH;
363                         goto error_put_ifp;
364                 }
365                 break;
366         case ADDR_SRC_ANY:
367                 /* check for loopback device */
368                 if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
369                         saddr = (struct sockaddr *)&dst_tmp;
370                 else
371                         saddr = rte->rt_ifa->ifa_addr;
372
373                 /* get destination network interface from route */
374                 ifp = rte->rt_ifp;
375                 dev_hold(ifp);
376                 break;
377         default:
378                 break;
379         }
380
381         /*
382          * Step 3 - resolve destination MAC address
383          */
384         if (dst_tmp.sin_addr.s_addr == INADDR_BROADCAST) {
385                 rdma_copy_addr_sub(edst, ifp->if_broadcastaddr,
386                     ifp->if_addrlen, MAX_ADDR_LEN);
387                 error = 0;
388         } else if (IN_MULTICAST(ntohl(dst_tmp.sin_addr.s_addr))) {
389                 bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
390                 error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp);
391                 if (error != 0)
392                         goto error_put_ifp;
393                 else if (is_gw)
394                         addr->network = RDMA_NETWORK_IPV4;
395         } else if (ifp->if_flags & IFF_LOOPBACK) {
396                 memset(edst, 0, MAX_ADDR_LEN);
397                 error = 0;
398         } else {
399                 bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
400                 memset(edst, 0, MAX_ADDR_LEN);
401                 error = arpresolve(ifp, is_gw, NULL, is_gw ?
402                     rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
403                     edst, NULL, NULL);
404                 if (error != 0)
405                         goto error_put_ifp;
406                 else if (is_gw)
407                         addr->network = RDMA_NETWORK_IPV4;
408         }
409
410         /*
411          * Step 4 - update source address, if any
412          */
413         if (saddr != NULL) {
414                 src_port = src_in->sin_port;
415                 memcpy(src_in, saddr, rdma_addr_size(saddr));
416                 src_in->sin_port = src_port;    /* preserve port number */
417         }
418
419         if (rte != NULL)
420                 RTFREE(rte);
421
422         *ifpp = ifp;
423
424         goto done;
425
426 error_put_ifp:
427         dev_put(ifp);
428 error_rt_free:
429         RTFREE(rte);
430 done:
431         CURVNET_RESTORE();
432
433         if (error == EWOULDBLOCK || error == EAGAIN)
434                 error = ENODATA;
435         return (-error);
436 }
437 #else
438 static int addr4_resolve(struct sockaddr_in *src_in,
439                          const struct sockaddr_in *dst_in,
440                          struct rdma_dev_addr *addr,
441                          u8 *edst,
442                          struct ifnet **ifpp)
443 {
444         return -EADDRNOTAVAIL;
445 }
446 #endif
447
448 #ifdef INET6
449 static int addr6_resolve(struct sockaddr_in6 *src_in,
450                          const struct sockaddr_in6 *dst_in,
451                          struct rdma_dev_addr *addr,
452                          u8 *edst,
453                          struct ifnet **ifpp)
454 {
455         enum {
456                 ADDR_VALID = 0,
457                 ADDR_SRC_ANY = 1,
458                 ADDR_DST_ANY = 2,
459         };
460         struct sockaddr_in6 dst_tmp = *dst_in;
461         in_port_t src_port;
462         struct sockaddr *saddr = NULL;
463         struct rtentry *rte;
464         struct ifnet *ifp;
465         int error;
466         int type;
467
468         /* set VNET, if any */
469         CURVNET_SET(addr->net);
470
471         /* set default TTL limit */
472         addr->hoplimit = V_ip_defttl;
473
474         type = ADDR_VALID;
475         if (ipv6_addr_any(&src_in->sin6_addr))
476                 type |= ADDR_SRC_ANY;
477         if (ipv6_addr_any(&dst_tmp.sin6_addr))
478                 type |= ADDR_DST_ANY;
479
480         /*
481          * Make sure the socket address length field
482          * is set, else rtalloc1() will fail.
483          */
484         dst_tmp.sin6_len = sizeof(dst_tmp);
485
486         /*
487          * Make sure the scope ID gets embedded, else rtalloc1() will
488          * resolve to the loopback interface.
489          */
490         dst_tmp.sin6_scope_id = addr->bound_dev_if;
491         sa6_embedscope(&dst_tmp, 0);
492
493         /* Step 1 - lookup destination route if any */
494         switch (type) {
495         case ADDR_VALID:
496                 /* sanity check for IPv4 addresses */
497                 if (ipv6_addr_v4mapped(&src_in->sin6_addr) !=
498                     ipv6_addr_v4mapped(&dst_tmp.sin6_addr)) {
499                         error = EAFNOSUPPORT;
500                         goto done;
501                 }
502                 /* FALLTHROUGH */
503         case ADDR_SRC_ANY:
504                 /* regular destination route lookup */
505                 rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
506                 if (rte == NULL) {
507                         error = EHOSTUNREACH;
508                         goto done;
509                 } else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
510                         RTFREE_LOCKED(rte);
511                         error = EHOSTUNREACH;
512                         goto done;
513                 }
514                 RT_UNLOCK(rte);
515                 break;
516         default:
517                 error = ENETUNREACH;
518                 goto done;
519         }
520
521         /* Step 2 - find outgoing network interface */
522         switch (type) {
523         case ADDR_VALID:
524                 /* get source interface */
525                 if (addr->bound_dev_if != 0) {
526                         ifp = dev_get_by_index(addr->net, addr->bound_dev_if);
527                 } else {
528                         ifp = ip6_dev_find(addr->net, src_in->sin6_addr, 0);
529                 }
530
531                 /* check source interface */
532                 if (ifp == NULL) {
533                         error = ENETUNREACH;
534                         goto error_rt_free;
535                 } else if (ifp->if_flags & IFF_LOOPBACK) {
536                         /*
537                          * Source address cannot be a loopback device.
538                          */
539                         error = EHOSTUNREACH;
540                         goto error_put_ifp;
541                 } else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
542                         if (memcmp(&src_in->sin6_addr, &dst_in->sin6_addr,
543                             sizeof(src_in->sin6_addr))) {
544                                 /*
545                                  * Destination is loopback, but source
546                                  * and destination address is not the
547                                  * same.
548                                  */
549                                 error = EHOSTUNREACH;
550                                 goto error_put_ifp;
551                         }
552                         /* get destination network interface from route */
553                         dev_put(ifp);
554                         ifp = rte->rt_ifp;
555                         dev_hold(ifp);
556                 } else if (ifp != rte->rt_ifp) {
557                         /*
558                          * Source and destination interfaces are
559                          * different.
560                          */
561                         error = ENETUNREACH;
562                         goto error_put_ifp;
563                 }
564                 break;
565         case ADDR_SRC_ANY:
566                 /* check for loopback device */
567                 if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
568                         saddr = (struct sockaddr *)&dst_tmp;
569                 else
570                         saddr = rte->rt_ifa->ifa_addr;
571
572                 /* get destination network interface from route */
573                 ifp = rte->rt_ifp;
574                 dev_hold(ifp);
575                 break;
576         default:
577                 break;
578         }
579
580         /*
581          * Step 3 - resolve destination MAC address
582          */
583         if (IN6_IS_ADDR_MULTICAST(&dst_tmp.sin6_addr)) {
584                 bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
585                 error = addr_resolve_multi(edst, ifp,
586                     (struct sockaddr *)&dst_tmp);
587                 if (error != 0)
588                         goto error_put_ifp;
589                 else if (is_gw)
590                         addr->network = RDMA_NETWORK_IPV6;
591         } else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
592                 memset(edst, 0, MAX_ADDR_LEN);
593                 error = 0;
594         } else {
595                 bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
596                 memset(edst, 0, MAX_ADDR_LEN);
597                 error = nd6_resolve(ifp, is_gw, NULL, is_gw ?
598                     rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
599                     edst, NULL, NULL);
600                 if (error != 0)
601                         goto error_put_ifp;
602                 else if (is_gw)
603                         addr->network = RDMA_NETWORK_IPV6;
604         }
605
606         /*
607          * Step 4 - update source address, if any
608          */
609         if (saddr != NULL) {
610                 src_port = src_in->sin6_port;
611                 memcpy(src_in, saddr, rdma_addr_size(saddr));
612                 src_in->sin6_port = src_port;   /* preserve port number */
613         }
614
615         if (rte != NULL)
616                 RTFREE(rte);
617
618         *ifpp = ifp;
619
620         goto done;
621
622 error_put_ifp:
623         dev_put(ifp);
624 error_rt_free:
625         RTFREE(rte);
626 done:
627         CURVNET_RESTORE();
628
629         if (error == EWOULDBLOCK || error == EAGAIN)
630                 error = ENODATA;
631         return (-error);
632 }
633 #else
634 static int addr6_resolve(struct sockaddr_in6 *src_in,
635                          const struct sockaddr_in6 *dst_in,
636                          struct rdma_dev_addr *addr,
637                          u8 *edst,
638                          struct ifnet **ifpp)
639 {
640         return -EADDRNOTAVAIL;
641 }
642 #endif
643
644 static int addr_resolve_neigh(struct ifnet *dev,
645                               const struct sockaddr *dst_in,
646                               u8 *edst,
647                               struct rdma_dev_addr *addr)
648 {
649         if (dev->if_flags & IFF_LOOPBACK) {
650                 int ret;
651
652                 /*
653                  * Binding to a loopback device is not allowed. Make
654                  * sure the destination device address is global by
655                  * clearing the bound device interface:
656                  */
657                 if (addr->bound_dev_if == dev->if_index)
658                         addr->bound_dev_if = 0;
659
660                 ret = rdma_translate_ip(dst_in, addr);
661                 if (ret == 0) {
662                         memcpy(addr->dst_dev_addr, addr->src_dev_addr,
663                                MAX_ADDR_LEN);
664                 }
665                 return ret;
666         }
667
668         /* If the device doesn't do ARP internally */
669         if (!(dev->if_flags & IFF_NOARP))
670                 return rdma_copy_addr(addr, dev, edst);
671
672         return rdma_copy_addr(addr, dev, NULL);
673 }
674
675 static int addr_resolve(struct sockaddr *src_in,
676                         const struct sockaddr *dst_in,
677                         struct rdma_dev_addr *addr)
678 {
679         struct epoch_tracker et;
680         struct net_device *ndev = NULL;
681         u8 edst[MAX_ADDR_LEN];
682         int ret;
683
684         if (dst_in->sa_family != src_in->sa_family)
685                 return -EINVAL;
686
687         NET_EPOCH_ENTER(et);
688         switch (src_in->sa_family) {
689         case AF_INET:
690                 ret = addr4_resolve((struct sockaddr_in *)src_in,
691                                     (const struct sockaddr_in *)dst_in,
692                                     addr, edst, &ndev);
693                 break;
694         case AF_INET6:
695                 ret = addr6_resolve((struct sockaddr_in6 *)src_in,
696                                     (const struct sockaddr_in6 *)dst_in, addr,
697                                     edst, &ndev);
698                 break;
699         default:
700                 ret = -EADDRNOTAVAIL;
701                 break;
702         }
703         NET_EPOCH_EXIT(et);
704
705         /* check for error */
706         if (ret != 0)
707                 return ret;
708
709         /* store MAC addresses and check for loopback */
710         ret = addr_resolve_neigh(ndev, dst_in, edst, addr);
711
712         /* set belonging VNET, if any */
713         addr->net = dev_net(ndev);
714         dev_put(ndev);
715
716         return ret;
717 }
718
719 static void process_req(struct work_struct *work)
720 {
721         struct addr_req *req, *temp_req;
722         struct sockaddr *src_in, *dst_in;
723         struct list_head done_list;
724
725         INIT_LIST_HEAD(&done_list);
726
727         mutex_lock(&lock);
728         list_for_each_entry_safe(req, temp_req, &req_list, list) {
729                 if (req->status == -ENODATA) {
730                         src_in = (struct sockaddr *) &req->src_addr;
731                         dst_in = (struct sockaddr *) &req->dst_addr;
732                         req->status = addr_resolve(src_in, dst_in, req->addr);
733                         if (req->status && time_after_eq(jiffies, req->timeout))
734                                 req->status = -ETIMEDOUT;
735                         else if (req->status == -ENODATA)
736                                 continue;
737                 }
738                 list_move_tail(&req->list, &done_list);
739         }
740
741         if (!list_empty(&req_list)) {
742                 req = list_entry(req_list.next, struct addr_req, list);
743                 set_timeout(req->timeout);
744         }
745         mutex_unlock(&lock);
746
747         list_for_each_entry_safe(req, temp_req, &done_list, list) {
748                 list_del(&req->list);
749                 req->callback(req->status, (struct sockaddr *) &req->src_addr,
750                         req->addr, req->context);
751                 put_client(req->client);
752                 kfree(req);
753         }
754 }
755
756 int rdma_resolve_ip(struct rdma_addr_client *client,
757                     struct sockaddr *src_addr, struct sockaddr *dst_addr,
758                     struct rdma_dev_addr *addr, int timeout_ms,
759                     void (*callback)(int status, struct sockaddr *src_addr,
760                                      struct rdma_dev_addr *addr, void *context),
761                     void *context)
762 {
763         struct sockaddr *src_in, *dst_in;
764         struct addr_req *req;
765         int ret = 0;
766
767         req = kzalloc(sizeof *req, GFP_KERNEL);
768         if (!req)
769                 return -ENOMEM;
770
771         src_in = (struct sockaddr *) &req->src_addr;
772         dst_in = (struct sockaddr *) &req->dst_addr;
773
774         if (src_addr) {
775                 if (src_addr->sa_family != dst_addr->sa_family) {
776                         ret = -EINVAL;
777                         goto err;
778                 }
779
780                 memcpy(src_in, src_addr, rdma_addr_size(src_addr));
781         } else {
782                 src_in->sa_family = dst_addr->sa_family;
783         }
784
785         memcpy(dst_in, dst_addr, rdma_addr_size(dst_addr));
786         req->addr = addr;
787         req->callback = callback;
788         req->context = context;
789         req->client = client;
790         atomic_inc(&client->refcount);
791
792         req->status = addr_resolve(src_in, dst_in, addr);
793         switch (req->status) {
794         case 0:
795                 req->timeout = jiffies;
796                 queue_req(req);
797                 break;
798         case -ENODATA:
799                 req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
800                 queue_req(req);
801                 break;
802         default:
803                 ret = req->status;
804                 atomic_dec(&client->refcount);
805                 goto err;
806         }
807         return ret;
808 err:
809         kfree(req);
810         return ret;
811 }
812 EXPORT_SYMBOL(rdma_resolve_ip);
813
814 int rdma_resolve_ip_route(struct sockaddr *src_addr,
815                           const struct sockaddr *dst_addr,
816                           struct rdma_dev_addr *addr)
817 {
818         struct sockaddr_storage ssrc_addr = {};
819         struct sockaddr *src_in = (struct sockaddr *)&ssrc_addr;
820
821         if (src_addr) {
822                 if (src_addr->sa_family != dst_addr->sa_family)
823                         return -EINVAL;
824
825                 memcpy(src_in, src_addr, rdma_addr_size(src_addr));
826         } else {
827                 src_in->sa_family = dst_addr->sa_family;
828         }
829
830         return addr_resolve(src_in, dst_addr, addr);
831 }
832 EXPORT_SYMBOL(rdma_resolve_ip_route);
833
834 void rdma_addr_cancel(struct rdma_dev_addr *addr)
835 {
836         struct addr_req *req, *temp_req;
837
838         mutex_lock(&lock);
839         list_for_each_entry_safe(req, temp_req, &req_list, list) {
840                 if (req->addr == addr) {
841                         req->status = -ECANCELED;
842                         req->timeout = jiffies;
843                         list_move(&req->list, &req_list);
844                         set_timeout(req->timeout);
845                         break;
846                 }
847         }
848         mutex_unlock(&lock);
849 }
850 EXPORT_SYMBOL(rdma_addr_cancel);
851
852 struct resolve_cb_context {
853         struct rdma_dev_addr *addr;
854         struct completion comp;
855         int status;
856 };
857
858 static void resolve_cb(int status, struct sockaddr *src_addr,
859              struct rdma_dev_addr *addr, void *context)
860 {
861         if (!status)
862                 memcpy(((struct resolve_cb_context *)context)->addr,
863                        addr, sizeof(struct rdma_dev_addr));
864         ((struct resolve_cb_context *)context)->status = status;
865         complete(&((struct resolve_cb_context *)context)->comp);
866 }
867
868 int rdma_addr_find_l2_eth_by_grh(const union ib_gid *sgid,
869                                  const union ib_gid *dgid,
870                                  u8 *dmac, struct net_device *dev,
871                                  int *hoplimit)
872 {
873         int ret = 0;
874         struct rdma_dev_addr dev_addr;
875         struct resolve_cb_context ctx;
876
877         union {
878                 struct sockaddr     _sockaddr;
879                 struct sockaddr_in  _sockaddr_in;
880                 struct sockaddr_in6 _sockaddr_in6;
881         } sgid_addr, dgid_addr;
882
883         rdma_gid2ip(&sgid_addr._sockaddr, sgid);
884         rdma_gid2ip(&dgid_addr._sockaddr, dgid);
885
886         memset(&dev_addr, 0, sizeof(dev_addr));
887
888         dev_addr.bound_dev_if = dev->if_index;
889         dev_addr.net = dev_net(dev);
890
891         ctx.addr = &dev_addr;
892         init_completion(&ctx.comp);
893         ret = rdma_resolve_ip(&self, &sgid_addr._sockaddr, &dgid_addr._sockaddr,
894                         &dev_addr, 1000, resolve_cb, &ctx);
895         if (ret)
896                 return ret;
897
898         wait_for_completion(&ctx.comp);
899
900         ret = ctx.status;
901         if (ret)
902                 return ret;
903
904         memcpy(dmac, dev_addr.dst_dev_addr, ETH_ALEN);
905         if (hoplimit)
906                 *hoplimit = dev_addr.hoplimit;
907         return ret;
908 }
909 EXPORT_SYMBOL(rdma_addr_find_l2_eth_by_grh);
910
911 int addr_init(void)
912 {
913         addr_wq = alloc_workqueue("ib_addr", WQ_MEM_RECLAIM, 0);
914         if (!addr_wq)
915                 return -ENOMEM;
916
917         rdma_addr_register_client(&self);
918
919         return 0;
920 }
921
922 void addr_cleanup(void)
923 {
924         rdma_addr_unregister_client(&self);
925         destroy_workqueue(addr_wq);
926 }