* Handles RTM_GET message from routing socket, returning matching rt. * * Returns: * 0 on success, with locked and referenced matching rt in @rt_nrt * errno of failure */
| 627 | * errno of failure |
| 628 | */ |
| 629 | static int |
| 630 | handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, |
| 631 | struct rt_msghdr *rtm, struct rib_cmd_info *rc) |
| 632 | { |
| 633 | RIB_RLOCK_TRACKER; |
| 634 | struct rib_head *rnh; |
| 635 | struct nhop_object *nh; |
| 636 | sa_family_t saf; |
| 637 | |
| 638 | saf = info->rti_info[RTAX_DST]->sa_family; |
| 639 | |
| 640 | rnh = rt_tables_get_rnh(fibnum, saf); |
| 641 | if (rnh == NULL) |
| 642 | return (EAFNOSUPPORT); |
| 643 | |
| 644 | RIB_RLOCK(rnh); |
| 645 | |
| 646 | /* |
| 647 | * By (implicit) convention host route (one without netmask) |
| 648 | * means longest-prefix-match request and the route with netmask |
| 649 | * means exact-match lookup. |
| 650 | * As cleanup_xaddrs() cleans up info flags&addrs for the /32,/128 |
| 651 | * prefixes, use original data to check for the netmask presence. |
| 652 | */ |
| 653 | if ((rtm->rtm_addrs & RTA_NETMASK) == 0) { |
| 654 | /* |
| 655 | * Provide longest prefix match for |
| 656 | * address lookup (no mask). |
| 657 | * 'route -n get addr' |
| 658 | */ |
| 659 | rc->rc_rt = (struct rtentry *) rnh->rnh_matchaddr( |
| 660 | info->rti_info[RTAX_DST], &rnh->head); |
| 661 | } else |
| 662 | rc->rc_rt = (struct rtentry *) rnh->rnh_lookup( |
| 663 | info->rti_info[RTAX_DST], |
| 664 | info->rti_info[RTAX_NETMASK], &rnh->head); |
| 665 | |
| 666 | if (rc->rc_rt == NULL) { |
| 667 | RIB_RUNLOCK(rnh); |
| 668 | return (ESRCH); |
| 669 | } |
| 670 | |
| 671 | nh = select_nhop(rt_get_raw_nhop(rc->rc_rt), info->rti_info[RTAX_GATEWAY]); |
| 672 | if (nh == NULL) { |
| 673 | RIB_RUNLOCK(rnh); |
| 674 | return (ESRCH); |
| 675 | } |
| 676 | /* |
| 677 | * If performing proxied L2 entry insertion, and |
| 678 | * the actual PPP host entry is found, perform |
| 679 | * another search to retrieve the prefix route of |
| 680 | * the local end point of the PPP link. |
| 681 | * TODO: move this logic to userland. |
| 682 | */ |
| 683 | if (rtm->rtm_flags & RTF_ANNOUNCE) { |
| 684 | struct sockaddr laddr; |
| 685 | |
| 686 | if (nh->nh_ifp != NULL && |
no test coverage detected