1
0
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:
david
2009-12-19 21:26:14 +00:00
parent 9f0e11f035
commit b838242e01
15 changed files with 593 additions and 517 deletions

View File

@@ -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++) {