* Sends the prepared reply message in @rtm to all rtsock clients. * Frees @m and @rtm. * */
| 1187 | * |
| 1188 | */ |
| 1189 | static void |
| 1190 | send_rtm_reply(struct socket *so, struct rt_msghdr *rtm, struct mbuf *m, |
| 1191 | sa_family_t saf, u_int fibnum, int rtm_errno) |
| 1192 | { |
| 1193 | struct rawcb *rp = NULL; |
| 1194 | |
| 1195 | /* |
| 1196 | * Check to see if we don't want our own messages. |
| 1197 | */ |
| 1198 | if ((so->so_options & SO_USELOOPBACK) == 0) { |
| 1199 | if (V_route_cb.any_count <= 1) { |
| 1200 | if (rtm != NULL) |
| 1201 | free(rtm, M_TEMP); |
| 1202 | m_freem(m); |
| 1203 | return; |
| 1204 | } |
| 1205 | /* There is another listener, so construct message */ |
| 1206 | rp = sotorawcb(so); |
| 1207 | } |
| 1208 | |
| 1209 | if (rtm != NULL) { |
| 1210 | if (rtm_errno!= 0) |
| 1211 | rtm->rtm_errno = rtm_errno; |
| 1212 | else |
| 1213 | rtm->rtm_flags |= RTF_DONE; |
| 1214 | |
| 1215 | m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm); |
| 1216 | if (m->m_pkthdr.len < rtm->rtm_msglen) { |
| 1217 | m_freem(m); |
| 1218 | m = NULL; |
| 1219 | } else if (m->m_pkthdr.len > rtm->rtm_msglen) |
| 1220 | m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len); |
| 1221 | |
| 1222 | free(rtm, M_TEMP); |
| 1223 | } |
| 1224 | if (m != NULL) { |
| 1225 | M_SETFIB(m, fibnum); |
| 1226 | m->m_flags |= RTS_FILTER_FIB; |
| 1227 | if (rp) { |
| 1228 | /* |
| 1229 | * XXX insure we don't get a copy by |
| 1230 | * invalidating our protocol |
| 1231 | */ |
| 1232 | unsigned short family = rp->rcb_proto.sp_family; |
| 1233 | rp->rcb_proto.sp_family = 0; |
| 1234 | rt_dispatch(m, saf); |
| 1235 | rp->rcb_proto.sp_family = family; |
| 1236 | } else |
| 1237 | rt_dispatch(m, saf); |
| 1238 | } |
| 1239 | } |
| 1240 | |
| 1241 | static void |
| 1242 | rt_getmetrics(const struct rtentry *rt, const struct nhop_object *nh, |
no test coverage detected