mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-28 16:43:09 +00:00
Allow diverted packets from the transmit side to remember if they
had a recv interface and allow that state to be available after re-injection for further tests.
This commit is contained in:
parent
0774c3c25a
commit
bab04eb816
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36903
@ -30,7 +30,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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"
|
#include "opt_inet.h"
|
||||||
@ -178,7 +178,6 @@ div_input(struct mbuf *m, int hlen)
|
|||||||
divsrc.sin_addr.s_addr = 0;
|
divsrc.sin_addr.s_addr = 0;
|
||||||
if (hlen) {
|
if (hlen) {
|
||||||
struct ifaddr *ifa;
|
struct ifaddr *ifa;
|
||||||
char name[32];
|
|
||||||
|
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
@ -200,6 +199,9 @@ div_input(struct mbuf *m, int hlen)
|
|||||||
((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
|
((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (m->m_pkthdr.rcvif) {
|
||||||
|
char name[32];
|
||||||
/*
|
/*
|
||||||
* Hide the actual interface name in there in the
|
* Hide the actual interface name in there in the
|
||||||
* sin_zero array. XXX This needs to be moved to a
|
* sin_zero array. XXX This needs to be moved to a
|
||||||
@ -267,21 +269,38 @@ div_output(so, m, addr, control)
|
|||||||
if (control)
|
if (control)
|
||||||
m_freem(control); /* XXX */
|
m_freem(control); /* XXX */
|
||||||
|
|
||||||
/* Loopback avoidance */
|
/* Loopback avoidance and state recovery */
|
||||||
if (sin) {
|
if (sin) {
|
||||||
|
int len = 0;
|
||||||
|
char *c = sin->sin_zero;
|
||||||
#ifdef IPFW_DIVERT_OLDRESTART
|
#ifdef IPFW_DIVERT_OLDRESTART
|
||||||
ip_divert_cookie = ntohs(sin->sin_port);
|
ip_divert_cookie = ntohs(sin->sin_port);
|
||||||
#else
|
#else
|
||||||
ip_divert_cookie = sin->sin_port;
|
ip_divert_cookie = sin->sin_port;
|
||||||
#endif /* IPFW_DIVERT_OLDRESTART */
|
#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 {
|
} else {
|
||||||
ip_divert_cookie = 0;
|
ip_divert_cookie = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reinject packet into the system as incoming or outgoing */
|
/* Reinject packet into the system as incoming or outgoing */
|
||||||
if (!sin || sin->sin_addr.s_addr == 0) {
|
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) ||
|
if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) ||
|
||||||
((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) {
|
((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) {
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
@ -298,30 +317,10 @@ div_output(so, m, addr, control)
|
|||||||
(so->so_options & SO_DONTROUTE) |
|
(so->so_options & SO_DONTROUTE) |
|
||||||
IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions);
|
IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions);
|
||||||
} else {
|
} else {
|
||||||
struct ifnet *ifp = NULL;
|
|
||||||
struct ifaddr *ifa;
|
struct ifaddr *ifa;
|
||||||
int len = 0;
|
|
||||||
char *c = sin->sin_zero;
|
|
||||||
|
|
||||||
sin->sin_port = 0;
|
/* If no luck with the name above. check by IP address. */
|
||||||
|
if (m->m_pkthdr.rcvif == NULL) {
|
||||||
/*
|
|
||||||
* 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 (!(ifa = ifa_ifwithaddr((struct sockaddr *) sin))) {
|
if (!(ifa = ifa_ifwithaddr((struct sockaddr *) sin))) {
|
||||||
error = EADDRNOTAVAIL;
|
error = EADDRNOTAVAIL;
|
||||||
goto cantsend;
|
goto cantsend;
|
||||||
|
Loading…
Reference in New Issue
Block a user