diff options
Diffstat (limited to 'sys/netinet/ip_divert.c')
-rw-r--r-- | sys/netinet/ip_divert.c | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index f6b850b30dfb..64aa114f8eab 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ip_divert.c,v 1.28 1998/06/06 19:39:08 julian Exp $ + * $Id: ip_divert.c,v 1.29 1998/06/06 20:45:25 julian Exp $ */ #include "opt_inet.h" @@ -178,7 +178,6 @@ div_input(struct mbuf *m, int hlen) divsrc.sin_addr.s_addr = 0; if (hlen) { struct ifaddr *ifa; - char name[32]; #ifdef DIAGNOSTIC /* Sanity check */ @@ -200,6 +199,9 @@ div_input(struct mbuf *m, int hlen) ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; break; } + } + if (m->m_pkthdr.rcvif) { + char name[32]; /* * Hide the actual interface name in there in the * sin_zero array. XXX This needs to be moved to a @@ -267,21 +269,38 @@ div_output(so, m, addr, control) if (control) m_freem(control); /* XXX */ - /* Loopback avoidance */ + /* Loopback avoidance and state recovery */ if (sin) { + int len = 0; + char *c = sin->sin_zero; #ifdef IPFW_DIVERT_OLDRESTART ip_divert_cookie = ntohs(sin->sin_port); #else ip_divert_cookie = sin->sin_port; #endif /* IPFW_DIVERT_OLDRESTART */ + + /* + * Find receive interface with the given name or IP address. + * The name is user supplied data so don't trust it's size or + * that it is zero terminated. The name has priority. + * We are presently assuming that the sockaddr_in + * has not been replaced by a sockaddr_div, so we limit it + * to 16 bytes in total. the name is stuffed (if it exists) + * in the sin_zero[] field. + */ + while (*c++ && (len++ < sizeof(sin->sin_zero))); + if ((len > 0) && (len < sizeof(sin->sin_zero))) + m->m_pkthdr.rcvif = ifunit(sin->sin_zero); } else { ip_divert_cookie = 0; } /* Reinject packet into the system as incoming or outgoing */ if (!sin || sin->sin_addr.s_addr == 0) { - /* Don't allow both user specified and setsockopt options, - and don't allow packet length sizes that will crash */ + /* + * Don't allow both user specified and setsockopt options, + * and don't allow packet length sizes that will crash + */ if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) || ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { error = EINVAL; @@ -298,30 +317,10 @@ div_output(so, m, addr, control) (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions); } else { - struct ifnet *ifp = NULL; struct ifaddr *ifa; - int len = 0; - char *c = sin->sin_zero; - - sin->sin_port = 0; - - /* - * Find receive interface with the given name or IP address. - * The name is user supplied data so don't trust it's size or - * that it is zero terminated. The name has priority. - * We are presently assuming that the sockaddr_in - * has not been replaced by a sockaddr_div, so we limit it - * to 16 bytes in total. the name is stuffed (if it exists) - * in the sin_zero[] field. - */ - while (*c++ && (len++ < sizeof(sin->sin_zero))); - if ((len > 0) && (len < sizeof(sin->sin_zero))) - ifp = ifunit(sin->sin_zero); - /* If no luck with the name. check by IP address. */ - if (ifp) { - m->m_pkthdr.rcvif = ifp; - } else { + /* If no luck with the name above. check by IP address. */ + if (m->m_pkthdr.rcvif == NULL) { if (!(ifa = ifa_ifwithaddr((struct sockaddr *) sin))) { error = EADDRNOTAVAIL; goto cantsend; |