mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 17:59:04 +00:00
Merge from /nmap-exp/david/nmap-mem. This brings in two memory-reducing
changes. The first is that Port objects don't allocate memory for service and RPC results unless that information is set. This reduces the size of a bare Port from 92 to 40 bytes on my machine. The second change is that PortList now has the notion of a "default port state," which is the state of any ports that didn't receive a response. These ports don't need an allocated Port object, which saves a lot of memory in scans where most ports didn't get a response.
This commit is contained in:
59
output.cc
59
output.cc
@@ -202,7 +202,7 @@ static char *xml_sf_convert(const char *str) {
|
||||
// the service name or the service fingerprint is non-null.
|
||||
// Returns a pointer to a buffer containing the element,
|
||||
// you will have to call free on it.
|
||||
static char *getServiceXMLBuf(struct serviceDeductions *sd) {
|
||||
static char *getServiceXMLBuf(const struct serviceDeductions *sd) {
|
||||
string versionxmlstring = "";
|
||||
char rpcbuf[128];
|
||||
char confBuf[20];
|
||||
@@ -466,33 +466,6 @@ int print_iflist(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fills in namebuf (as long as there is space in buflen) with the
|
||||
Name nmap normal output will use to describe the port. This takes
|
||||
into account to confidence level, any SSL tunneling, etc. Truncates
|
||||
namebuf to 0 length if there is no room.*/
|
||||
static void getNmapServiceName(struct serviceDeductions *sd, int state,
|
||||
char *namebuf, int buflen) {
|
||||
const char *tunnel_prefix;
|
||||
int len;
|
||||
|
||||
if (sd->service_tunnel == SERVICE_TUNNEL_SSL)
|
||||
tunnel_prefix = "ssl/";
|
||||
else
|
||||
tunnel_prefix = "";
|
||||
|
||||
if (sd->name != NULL && strcmp(sd->name, "unknown") != 0) {
|
||||
/* The port has a name and the name is not "unknown". How confident are we? */
|
||||
if (o.servicescan && state == PORT_OPEN && sd->name_confidence <= 5)
|
||||
len = Snprintf(namebuf, buflen, "%s%s?", tunnel_prefix, sd->name);
|
||||
else
|
||||
len = Snprintf(namebuf, buflen, "%s%s", tunnel_prefix, sd->name);
|
||||
} else {
|
||||
len = Snprintf(namebuf, buflen, "%sunknown", tunnel_prefix);
|
||||
}
|
||||
if (len >= buflen || len < 0)
|
||||
namebuf[0] = '\0';
|
||||
}
|
||||
|
||||
#ifndef NOLUA
|
||||
static char *formatScriptOutput(ScriptResult sr) {
|
||||
std::string result = std::string(), output = sr.get_output();
|
||||
@@ -549,6 +522,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
int first = 1;
|
||||
struct protoent *proto;
|
||||
Port *current;
|
||||
Port port;
|
||||
char hostname[1200];
|
||||
struct serviceDeductions sd;
|
||||
NmapOutputTable *Tbl = NULL;
|
||||
@@ -561,6 +535,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
unsigned int rowno;
|
||||
int numrows;
|
||||
int numignoredports = plist->numIgnoredPorts();
|
||||
int numports = plist->numPorts();
|
||||
|
||||
vector<const char *> saved_servicefps;
|
||||
|
||||
@@ -579,7 +554,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
prevstate = istate;
|
||||
}
|
||||
|
||||
if (numignoredports == plist->numports) {
|
||||
if (numignoredports == numports) {
|
||||
if (numignoredports == 0) {
|
||||
log_write(LOG_PLAIN, "0 ports scanned on %s\n",
|
||||
currenths->NameIP(hostname, sizeof(hostname)));
|
||||
@@ -666,7 +641,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
if (o.servicescan || o.rpcscan)
|
||||
versioncol = colno++;
|
||||
|
||||
numrows = plist->numports - numignoredports;
|
||||
numrows = numports - numignoredports;
|
||||
|
||||
#ifndef NOLUA
|
||||
int scriptrows = 0;
|
||||
@@ -697,7 +672,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
rowno = 1;
|
||||
if (o.ipprotscan) {
|
||||
current = NULL;
|
||||
while ((current = plist->nextPort(current, IPPROTO_IP, 0)) != NULL) {
|
||||
while ((current = plist->nextPort(current, &port, IPPROTO_IP, 0)) != NULL) {
|
||||
if (!plist->isIgnoredState(current->state)) {
|
||||
if (!first)
|
||||
log_write(LOG_MACHINE, ", ");
|
||||
@@ -730,8 +705,10 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char fullversion[160];
|
||||
|
||||
current = NULL;
|
||||
while ((current = plist->nextPort(current, TCPANDUDPANDSCTP, 0)) != NULL) {
|
||||
while ((current = plist->nextPort(current, &port, TCPANDUDPANDSCTP, 0)) != NULL) {
|
||||
if (!plist->isIgnoredState(current->state)) {
|
||||
if (!first)
|
||||
log_write(LOG_MACHINE, ", ");
|
||||
@@ -740,7 +717,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
strcpy(protocol, IPPROTO2STR(current->proto));
|
||||
Snprintf(portinfo, sizeof(portinfo), "%d/%s", current->portno, protocol);
|
||||
state = statenum2str(current->state);
|
||||
current->getServiceDeductions(&sd);
|
||||
plist->getServiceDeductions(current->portno, current->proto, &sd);
|
||||
if (sd.service_fp && saved_servicefps.size() <= 8)
|
||||
saved_servicefps.push_back(sd.service_fp);
|
||||
|
||||
@@ -783,7 +760,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
(sd.name) ? sd.name : ((*rpcinfo) ? "" : "unknown"),
|
||||
(sd.name) ? " " : "", rpcinfo);
|
||||
} else {
|
||||
getNmapServiceName(&sd, current->state, serviceinfo, sizeof(serviceinfo));
|
||||
current->getNmapServiceName(serviceinfo, sizeof(serviceinfo));
|
||||
rpcmachineinfo[0] = '\0';
|
||||
}
|
||||
Tbl->addItem(rowno, portcol, true, portinfo);
|
||||
@@ -792,8 +769,9 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
if (o.reason)
|
||||
Tbl->addItem(rowno, reasoncol, true, port_reason_str(current->reason));
|
||||
|
||||
if (*sd.fullversion)
|
||||
Tbl->addItem(rowno, versioncol, true, sd.fullversion);
|
||||
sd.populateFullVersionString(fullversion, sizeof(fullversion));
|
||||
if (*fullversion)
|
||||
Tbl->addItem(rowno, versioncol, true, fullversion);
|
||||
|
||||
// How should we escape illegal chars in grepable output?
|
||||
// Well, a reasonably clean way would be backslash escapes
|
||||
@@ -801,7 +779,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
// out fields with awk, cut, and such. So I'm gonna use the
|
||||
// ugly hat (fitting to grepable output) or replacing the '/'
|
||||
// character with '|' in the version field.
|
||||
Strncpy(grepvers, sd.fullversion, sizeof(grepvers) / sizeof(*grepvers));
|
||||
Strncpy(grepvers, fullversion, sizeof(grepvers) / sizeof(*grepvers));
|
||||
p = grepvers;
|
||||
while ((p = strchr(p, '/'))) {
|
||||
*p = '|';
|
||||
@@ -840,7 +818,7 @@ void printportoutput(Target * currenths, PortList * plist) {
|
||||
rowno++;
|
||||
#ifndef NOLUA
|
||||
if (o.script) {
|
||||
ScriptResults::iterator ssr_iter;
|
||||
ScriptResults::const_iterator ssr_iter;
|
||||
|
||||
for (ssr_iter = current->scriptResults.begin();
|
||||
ssr_iter != current->scriptResults.end(); ssr_iter++) {
|
||||
@@ -1907,6 +1885,7 @@ static int hostcmp(const char *a, const char *b) {
|
||||
scan (if it was performed) */
|
||||
void printserviceinfooutput(Target * currenths) {
|
||||
Port *p = NULL;
|
||||
Port port;
|
||||
struct serviceDeductions sd;
|
||||
int i, numhostnames = 0, numostypes = 0, numdevicetypes = 0;
|
||||
char hostname_tbl[MAX_SERVICE_INFO_FIELDS][MAXHOSTNAMELEN];
|
||||
@@ -1917,12 +1896,12 @@ void printserviceinfooutput(Target * currenths) {
|
||||
for (i = 0; i < MAX_SERVICE_INFO_FIELDS; i++)
|
||||
hostname_tbl[i][0] = ostype_tbl[i][0] = devicetype_tbl[i][0] = '\0';
|
||||
|
||||
while ((p = currenths->ports.nextPort(p, TCPANDUDPANDSCTP, PORT_OPEN))) {
|
||||
while ((p = currenths->ports.nextPort(p, &port, TCPANDUDPANDSCTP, PORT_OPEN))) {
|
||||
// The following 2 lines (from portlist.h) tell us that we don't need to
|
||||
// worry about free()ing anything in the serviceDeductions struct. pass in
|
||||
// an allocated struct serviceDeductions (don't wory about initializing, and
|
||||
// you don't have to free any internal ptrs.
|
||||
p->getServiceDeductions(&sd);
|
||||
currenths->ports.getServiceDeductions(p->portno, p->proto, &sd);
|
||||
|
||||
if (sd.hostname && !hostcmp(currenths->HostName(), sd.hostname)) {
|
||||
for (i = 0; i < MAX_SERVICE_INFO_FIELDS; i++) {
|
||||
|
||||
Reference in New Issue
Block a user