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