+/*
+ * Given address of next destination (final or next hop),
+ * return internet address info of interface to be used to get there.
+ */
+struct in_ifaddr *
+ip_rtaddr(dst)
+ struct in_addr dst;
+{
+ register struct sockaddr_in *sin;
+ register struct in_ifaddr *ia;
+
+ sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
+
+ if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
+ if (ipforward_rt.ro_rt) {
+ RTFREE(ipforward_rt.ro_rt);
+ ipforward_rt.ro_rt = 0;
+ }
+ sin->sin_family = AF_INET;
+ sin->sin_addr = dst;
+
+ rtalloc(&ipforward_rt);
+ }
+ if (ipforward_rt.ro_rt == 0)
+ return ((struct in_ifaddr *)0);
+ /*
+ * Find address associated with outgoing interface.
+ */
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_ifp == ipforward_rt.ro_rt->rt_ifp)
+ break;
+ return (ia);
+}
+
+/*
+ * Save incoming source route for use in replies,
+ * to be picked up later by ip_srcroute if the receiver is interested.
+ */
+save_rte(option, dst)
+ u_char *option;
+ struct in_addr dst;
+{
+ unsigned olen;
+ extern ipprintfs;
+
+ olen = option[IPOPT_OLEN];
+ if (olen > sizeof(ip_srcrt) - 1) {
+ if (ipprintfs)
+ printf("save_rte: olen %d\n", olen);
+ return;
+ }
+ bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
+ ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
+ ip_srcrt.route[ip_nhops++] = dst;
+}
+
+/*
+ * Retrieve incoming source route for use in replies,
+ * in the same form used by setsockopt.
+ * The first hop is placed before the options, will be removed later.
+ */
+struct mbuf *
+ip_srcroute()
+{
+ register struct in_addr *p, *q;
+ register struct mbuf *m;
+
+ if (ip_nhops == 0)
+ return ((struct mbuf *)0);
+ m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1;
+
+ /*
+ * First save first hop for return route
+ */
+ p = &ip_srcrt.route[ip_nhops - 1];
+ *(mtod(m, struct in_addr *)) = *p--;
+
+ /*
+ * Copy option fields and padding (nop) to mbuf.
+ */
+ ip_srcrt.nop = IPOPT_NOP;
+ bcopy((caddr_t)&ip_srcrt, mtod(m, caddr_t) + sizeof(struct in_addr),
+ IPOPT_OFFSET + 1 + 1);
+ q = (struct in_addr *)(mtod(m, caddr_t) +
+ sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1);
+ /*
+ * Record return path as an IP source route,
+ * reversing the path (pointers are now aligned).
+ */
+ while (p >= ip_srcrt.route)
+ *q++ = *p--;
+ return (m);
+}
+