mirror of
https://github.com/nmap/nmap.git
synced 2026-08-04 06:40:48 +00:00
Avoid up to 2 portlist lookups when setting port state in ultrascan
This commit is contained in:
parent
e75a253d72
commit
c5f3665c4f
3 changed files with 47 additions and 51 deletions
|
|
@ -459,8 +459,7 @@ void PortList::setDefaultPortState(u8 protocol, int state) {
|
|||
default_port_state[proto].state = state;
|
||||
}
|
||||
|
||||
void PortList::setPortState(u16 portno, u8 protocol, int state) {
|
||||
const Port *oldport;
|
||||
void PortList::setPortState(u16 portno, u8 protocol, int state, int *oldstate) {
|
||||
Port *current;
|
||||
int proto = INPROTO2PORTLISTPROTO(protocol);
|
||||
|
||||
|
|
@ -492,8 +491,10 @@ void PortList::setPortState(u16 portno, u8 protocol, int state) {
|
|||
error("Duplicate port (%hu/%s)", portno, proto2ascii_lowercase(protocol));
|
||||
}
|
||||
state_counts_proto[proto][current->state]--;
|
||||
if (oldstate) *oldstate = current->state;
|
||||
} else {
|
||||
state_counts_proto[proto][default_port_state[proto].state]--;
|
||||
if (oldstate) *oldstate = PORT_TESTING;
|
||||
}
|
||||
|
||||
current->state = state;
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ class PortList {
|
|||
static void freePortMap();
|
||||
|
||||
void setDefaultPortState(u8 protocol, int state);
|
||||
void setPortState(u16 portno, u8 protocol, int state);
|
||||
void setPortState(u16 portno, u8 protocol, int state, int *oldstate=NULL);
|
||||
int getPortState(u16 portno, u8 protocol);
|
||||
int forgetPort(u16 portno, u8 protocol);
|
||||
bool portIsDefault(u16 portno, u8 protocol);
|
||||
|
|
|
|||
|
|
@ -1859,57 +1859,52 @@ static bool ultrascan_port_pspec_update(UltraScanInfo *USI,
|
|||
portno = pspec->pd.sctp.dport;
|
||||
} else assert(0);
|
||||
|
||||
if (hss->target->ports.portIsDefault(portno, proto)) {
|
||||
oldstate = PORT_TESTING;
|
||||
hss->ports_finished++;
|
||||
} else {
|
||||
oldstate = hss->target->ports.getPortState(portno, proto);
|
||||
}
|
||||
// Set new port state, pending checks for valid state transitions
|
||||
hss->target->ports.setPortState(portno, proto, newstate, &oldstate);
|
||||
|
||||
/* printf("TCP port %hu has changed from state %s to %s!\n", portno, statenum2str(oldstate), statenum2str(newstate)); */
|
||||
switch (oldstate) {
|
||||
/* TODO: I need more code here to determine when a state should
|
||||
be overridden, for example PORT_OPEN trumps PORT_FILTERED
|
||||
in a SYN scan, but not necessarily for UDP scan */
|
||||
case PORT_TESTING:
|
||||
/* Brand new port -- add it to the list */
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
break;
|
||||
case PORT_OPEN:
|
||||
if (newstate != PORT_OPEN) {
|
||||
if (noresp_open_scan) {
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
} /* Otherwise The old open takes precedence */
|
||||
if (newstate != oldstate) {
|
||||
// Check for conditions that mean we should ignore newstate (revert to oldstate)
|
||||
switch (oldstate) {
|
||||
/* TODO: I need more code here to determine when a state should
|
||||
be overridden, for example PORT_OPEN trumps PORT_FILTERED
|
||||
in a SYN scan, but not necessarily for UDP scan */
|
||||
case PORT_TESTING:
|
||||
/* Brand new port -- add it to the list */
|
||||
hss->ports_finished++;
|
||||
break;
|
||||
case PORT_OPEN:
|
||||
// Changing from open to anything else only valid for noresp_open_scan
|
||||
if (!noresp_open_scan) {
|
||||
hss->target->ports.setPortState(portno, proto, oldstate);
|
||||
}
|
||||
break;
|
||||
case PORT_CLOSED:
|
||||
// Changing from closed to filtered is never allowed.
|
||||
// Changing from closed to anything else is never valid for noresp_open_scan
|
||||
if (noresp_open_scan || newstate == PORT_FILTERED)
|
||||
hss->target->ports.setPortState(portno, proto, oldstate);
|
||||
break;
|
||||
case PORT_FILTERED:
|
||||
// Changing from filtered to open is not allowed for noresp_open_scan
|
||||
if (noresp_open_scan && newstate == PORT_OPEN)
|
||||
hss->target->ports.setPortState(portno, proto, oldstate);
|
||||
break;
|
||||
case PORT_UNFILTERED:
|
||||
/* This could happen in an ACK scan if I receive a RST and then an
|
||||
ICMP filtered message. I'm gonna stick with unfiltered in that
|
||||
case. I'll change it if the new state is open or closed,
|
||||
though I don't expect that to ever happen */
|
||||
if (newstate != PORT_OPEN && newstate != PORT_CLOSED)
|
||||
hss->target->ports.setPortState(portno, proto, oldstate);
|
||||
break;
|
||||
case PORT_OPENFILTERED:
|
||||
// Always accepted.
|
||||
break;
|
||||
default:
|
||||
fatal("Unexpected port state: %d\n", oldstate);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PORT_CLOSED:
|
||||
if (newstate != PORT_CLOSED) {
|
||||
if (!noresp_open_scan && newstate != PORT_FILTERED)
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
}
|
||||
break;
|
||||
case PORT_FILTERED:
|
||||
if (newstate != PORT_FILTERED) {
|
||||
if (!noresp_open_scan || newstate != PORT_OPEN)
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
}
|
||||
break;
|
||||
case PORT_UNFILTERED:
|
||||
/* This could happen in an ACK scan if I receive a RST and then an
|
||||
ICMP filtered message. I'm gonna stick with unfiltered in that
|
||||
case. I'll change it if the new state is open or closed,
|
||||
though I don't expect that to ever happen */
|
||||
if (newstate == PORT_OPEN || newstate == PORT_CLOSED)
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
break;
|
||||
case PORT_OPENFILTERED:
|
||||
if (newstate != PORT_OPENFILTERED) {
|
||||
hss->target->ports.setPortState(portno, proto, newstate);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal("Unexpected port state: %d\n", oldstate);
|
||||
break;
|
||||
}
|
||||
|
||||
return oldstate != newstate;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue