+ case RTM_ADD:
+ if ((flags & RTF_GATEWAY) == 0) {
+ /*
+ * If we are adding a route to an interface,
+ * and the interface is a pt to pt link
+ * we should search for the destination
+ * as our clue to the interface. Otherwise
+ * we can use the local address.
+ */
+ ifa = 0;
+ if (flags & RTF_HOST)
+ ifa = ifa_ifwithdstaddr(dst);
+ if (ifa == 0)
+ ifa = ifa_ifwithaddr(gateway);
+ } else {
+ /*
+ * If we are adding a route to a remote net
+ * or host, the gateway may still be on the
+ * other end of a pt to pt link.
+ */
+ ifa = ifa_ifwithdstaddr(gateway);
+ }
+ if (ifa == 0) {
+ ifa = ifa_ifwithnet(gateway);
+ if (ifa == 0 && req == RTM_ADD)
+ senderr(ENETUNREACH);
+ }
+ len = sizeof (*rt) + ROUNDUP(gateway->sa_len)
+ + ROUNDUP(dst->sa_len) + ROUNDUP(ifa->ifa_llinfolen);
+ R_Malloc(rt, struct rtentry *, len);
+ if (rt == 0)
+ senderr(ENOBUFS);
+ Bzero(rt, len);
+ ndst = (struct sockaddr *)(rt + 1);
+ if (netmask) {
+ rt_maskedcopy(dst, ndst, netmask);
+ } else
+ Bcopy(dst, ndst, dst->sa_len);
+ rn = rn_addroute((caddr_t)ndst, (caddr_t)netmask,
+ rnh->rnh_treetop, rt->rt_nodes);
+ if (rn == 0) {
+ free((caddr_t)rt, M_RTABLE);
+ senderr(EEXIST);
+ }
+ rt->rt_ifp = ifa->ifa_ifp;
+ rt->rt_ifa = ifa;
+ if (ret_nrt) {
+ *ret_nrt = rt;
+ rt->rt_refcnt++;
+ }
+ rt->rt_flags = RTF_UP | flags;
+ rn->rn_key = (caddr_t) ndst; /* == rt_dst */
+ rt->rt_gateway = (struct sockaddr *)
+ (rn->rn_key + ROUNDUP(dst->sa_len));
+ Bcopy(gateway, rt->rt_gateway, gateway->sa_len);
+ rt->rt_llinfo = ROUNDUP(gateway->sa_len)
+ + (caddr_t)rt->rt_gateway;
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_ADD, rt, (struct sockaddr *)0);