+ dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+ if (cmd == RTM_DELETE) {
+ if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+ m = m_get(M_WAIT, MT_SONAME);
+ deldst = mtod(m, struct sockaddr *);
+ rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
+ dst = deldst;
+ }
+ if (rt = rtalloc1(dst, 0)) {
+ rt->rt_refcnt--;
+ if (rt->rt_ifa != ifa) {
+ if (m)
+ (void) m_free(m);
+ return (flags & RTF_HOST ? EHOSTUNREACH
+ : ENETUNREACH);
+ }
+ }
+ }
+ error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
+ flags | ifa->ifa_flags, &nrt);
+ if (m)
+ (void) m_free(m);
+ if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
+ rt_newaddrmsg(cmd, ifa, error, nrt);
+ if (rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++;
+ rtfree(rt);
+ }
+ }
+ if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
+ rt->rt_refcnt--;
+ if (rt->rt_ifa != ifa) {
+ printf("rtinit: wrong ifa (%x) was (%x)\n", ifa,
+ rt->rt_ifa);
+ if (rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
+ IFAFREE(rt->rt_ifa);
+ rt->rt_ifa = ifa;
+ rt->rt_ifp = ifa->ifa_ifp;
+ ifa->ifa_refcnt++;
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
+ }
+ rt_newaddrmsg(cmd, ifa, error, nrt);
+ }
+ return (error);