Пример #1
0
/*
 * Build the gmon.out file.
 */
void
dumpstate(struct kvmvars *kvp)
{
	register FILE *fp;
	struct rawarc rawarc;
	struct tostruct *tos;
	u_long frompc;
	u_short *froms, *tickbuf;
	size_t i;
	int mib[3];
	struct gmonhdr h;
	int fromindex, endfrom, toindex;

	setprof(kvp, GMON_PROF_OFF);
	fp = fopen("gmon.out", "w");
	if (fp == 0) {
		warn("gmon.out");
		return;
	}

	/*
	 * Build the gmon header and write it to a file.
	 */
	bzero(&h, sizeof(h));
	h.lpc = kvp->gpm.lowpc;
	h.hpc = kvp->gpm.highpc;
	h.ncnt = kvp->gpm.kcountsize + sizeof(h);
	h.version = GMONVERSION;
	h.profrate = kvp->gpm.profrate;
	h.histcounter_type = kvp->gpm.histcounter_type;
	fwrite((char *)&h, sizeof(h), 1, fp);

	/*
	 * Write out the tick buffer.
	 */
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROF;
	if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL)
		errx(5, "cannot allocate kcount space");
	if (kflag) {
		i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf,
		    kvp->gpm.kcountsize);
	} else {
		mib[2] = GPROF_COUNT;
		i = kvp->gpm.kcountsize;
		if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0)
			i = 0;
	}
	if (i != kvp->gpm.kcountsize)
		errx(6, "read ticks: read %lu, got %ld: %s",
		    kvp->gpm.kcountsize, (long)i,
		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
	if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1)
		err(7, "writing tocks to gmon.out");
	free(tickbuf);

	/*
	 * Write out the arc info.
	 */
	if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL)
		errx(8, "cannot allocate froms space");
	if (kflag) {
		i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms,
		    kvp->gpm.fromssize);
	} else {
		mib[2] = GPROF_FROMS;
		i = kvp->gpm.fromssize;
		if (sysctl(mib, 3, froms, &i, NULL, 0) < 0)
			i = 0;
	}
	if (i != kvp->gpm.fromssize)
		errx(9, "read froms: read %lu, got %ld: %s",
		    kvp->gpm.fromssize, (long)i,
		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
	if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL)
		errx(10, "cannot allocate tos space");
	if (kflag) {
		i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos,
		    kvp->gpm.tossize);
	} else {
		mib[2] = GPROF_TOS;
		i = kvp->gpm.tossize;
		if (sysctl(mib, 3, tos, &i, NULL, 0) < 0)
			i = 0;
	}
	if (i != kvp->gpm.tossize)
		errx(11, "read tos: read %lu, got %ld: %s",
		    kvp->gpm.tossize, (long)i,
		    kflag ? kvm_geterr(kvp->kd) : strerror(errno));
	if (debug)
		warnx("lowpc 0x%lx, textsize 0x%lx",
		    (unsigned long)kvp->gpm.lowpc, kvp->gpm.textsize);
	endfrom = kvp->gpm.fromssize / sizeof(*froms);
	for (fromindex = 0; fromindex < endfrom; ++fromindex) {
		if (froms[fromindex] == 0)
			continue;
		frompc = (u_long)kvp->gpm.lowpc +
		    (fromindex * kvp->gpm.hashfraction * sizeof(*froms));
		for (toindex = froms[fromindex]; toindex != 0;
		     toindex = tos[toindex].link) {
			if (debug)
				warnx("[mcleanup] frompc 0x%lx selfpc 0x%lx "
				    "count %ld", frompc, tos[toindex].selfpc,
				    tos[toindex].count);
			rawarc.raw_frompc = frompc;
			rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
			rawarc.raw_count = tos[toindex].count;
			fwrite((char *)&rawarc, sizeof(rawarc), 1, fp);
		}
	}
	fclose(fp);
}
Пример #2
0
int
port_in_use(const char *if_name,
            unsigned eport, int proto,
            const char *iaddr, unsigned iport)
{
	int found = 0;
	char ip_addr_str[INET_ADDRSTRLEN];
	struct in_addr ip_addr;
#ifdef __linux__
	/* linux code */
	char line[256];
	FILE *f;
	const char * tcpfile = "/proc/net/tcp";
	const char * udpfile = "/proc/net/udp";
#endif

	if(getifaddr(if_name, ip_addr_str, INET_ADDRSTRLEN, &ip_addr, NULL) < 0) {
		ip_addr.s_addr = 0;
		ip_addr_str[0] = '\0';
	}

	syslog(LOG_DEBUG, "Check protocol %s for port %u on ext_if %s %s, %08X",
	    (proto==IPPROTO_TCP)?"tcp":"udp", eport, if_name,
	    ip_addr_str, (unsigned)ip_addr.s_addr);

	/* Phase 1 : check for local sockets (would be listed by netstat) */
#if defined(__linux__)
	f = fopen((proto==IPPROTO_TCP)?tcpfile:udpfile, "r");
	if (!f) {
		syslog(LOG_ERR, "cannot open %s", (proto==IPPROTO_TCP)?tcpfile:udpfile);
		return -1;
	}

	while (fgets(line, 255, f)) {
		char eaddr[68];
		unsigned tmp_port;
		if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
				"%*x:%*x %*x %*d %*d %*llu",
				eaddr, &tmp_port) == 2
		) {
			/* TODO add IPV6 support if enabled
			 * Presently assumes IPV4 */
#ifdef DEBUG
			syslog(LOG_DEBUG, "port_in_use check port %u and address %s", tmp_port, eaddr);
#endif
			if (tmp_port == eport) {
				char tmp_addr[4];
				struct in_addr *tmp_ip_addr = (struct in_addr *)tmp_addr;
				if (sscanf(eaddr,"%2hhx%2hhx%2hhx%2hhx",
					&tmp_addr[3],&tmp_addr[2],&tmp_addr[1],&tmp_addr[0]) == 4)
				{
					if (tmp_ip_addr->s_addr == 0 || tmp_ip_addr->s_addr == ip_addr.s_addr)
					{
						found++;
						break;  /* don't care how many, just that we found at least one */
					}
				}
			}
		}
	}
	fclose(f);

#elif defined(__OpenBSD__)
static struct nlist list[] = {
#if 0
        {"_tcpstat", 0, 0, 0, 0},
        {"_udpstat", 0, 0, 0, 0},
        {"_tcbinfo", 0, 0, 0, 0},
        {"_udbinfo", 0, 0, 0, 0},
#endif
		{"_tcbtable", 0, 0, 0, 0},
		{"_udbtable", 0, 0, 0, 0},
        {NULL,0, 0, 0, 0}
};
	char errstr[_POSIX2_LINE_MAX];
	kvm_t *kd;
	ssize_t n;
	struct inpcbtable table;
	struct inpcb *next;
	struct inpcb inpcb;
	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errstr);
	if(!kd) {
		syslog(LOG_ERR, "%s: kvm_openfiles(): %s",
		       "portinuse()", errstr);
		return -1;
	}
	if(kvm_nlist(kd, list) < 0) {
		syslog(LOG_ERR, "%s: kvm_nlist(): %s",
		       "portinuse()", kvm_geterr(kd));
		kvm_close(kd);
		return -1;
	}
	n = kvm_read(kd, list[(proto==IPPROTO_TCP)?0:1].n_value, &table, sizeof(table));
	if(n < 0) {
		syslog(LOG_ERR, "%s: kvm_read(): %s",
		       "portinuse()", kvm_geterr(kd));
		kvm_close(kd);
		return -1;
	}
	next = CIRCLEQ_FIRST(&table.inpt_queue); /*TAILQ_FIRST(&table.inpt_queue);*/
	while(next != NULL) {
		if(((u_long)next & 3) != 0) break;
		n = kvm_read(kd, (u_long)next, &inpcb, sizeof(inpcb));
		if(n < 0) {
			syslog(LOG_ERR, "kvm_read(): %s", kvm_geterr(kd));
			break;
		}
		next = CIRCLEQ_NEXT(&inpcb, inp_queue);	/*TAILQ_NEXT(&inpcb, inp_queue);*/
		/* skip IPv6 sockets */
		if((inpcb.inp_flags & INP_IPV6) != 0)
			continue;
#ifdef DEBUG
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu",
		       (u_long)inpcb.inp_laddr.s_addr, ntohs(inpcb.inp_lport),
		       (u_long)inpcb.inp_faddr.s_addr, ntohs(inpcb.inp_fport));
#endif
		if(eport == (unsigned)ntohs(inpcb.inp_lport)) {
			if(inpcb.inp_laddr.s_addr == INADDR_ANY || inpcb.inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	kvm_close(kd);

#elif defined(__DragonFly__)
	const char *varname;
	struct xinpcb *xip;
	struct xtcpcb *xtp;
	struct inpcb *inp;
	void *buf = NULL;
	void *so_begin, *so_end;

	size_t len;

	switch (proto) {
	case IPPROTO_TCP:
		varname = "net.inet.tcp.pcblist";
		break;
	case IPPROTO_UDP:
		varname = "net.inet.udp.pcblist";
		break;
	default:
		syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto);
		return -1;
	}

	if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname);
		return -1;
	}
	buf = malloc(len);
	if (buf == NULL) {
		syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len);
		return -1;
	}
	if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname);
		free(buf);
		return -1;
	}

	so_begin = buf;
	so_end = (uint8_t *)buf + len;
	for (so_begin = buf, so_end = (uint8_t *)so_begin + len;
	     (uint8_t *)so_begin + sizeof(size_t) < (uint8_t *)so_end &&
	     (uint8_t *)so_begin + *(size_t *)so_begin <= (uint8_t *)so_end;
	     so_begin = (uint8_t *)so_begin + *(size_t *)so_begin) {
		switch (proto) {
		case IPPROTO_TCP:
			xtp = (struct xtcpcb *)so_begin;
			if (xtp->xt_len != sizeof *xtp) {
				syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld",
				       (long)xtp->xt_len, sizeof *xtp);
				free(buf);
				return -1;
			}
			inp = &xtp->xt_inp;
			break;
		case IPPROTO_UDP:
			xip = (struct xinpcb *)so_begin;
			if (xip->xi_len != sizeof *xip) {
				syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld",
				       (long)xip->xi_len, sizeof *xip);
				free(buf);
				return -1;
			}
			inp = &xip->xi_inp;
			break;
		default:
			abort();
		}
		/* no support for IPv6 */
		if (INP_ISIPV6(inp) != 0)
			continue;
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu",
		       (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport),
		       (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport),
		       eport, (u_long)ip_addr.s_addr, iport
		);
		if (eport == (unsigned)ntohs(inp->inp_lport)) {
			if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	if (buf) {
		free(buf);
		buf = NULL;
	}
#elif defined(__FreeBSD__)
	const char *varname;
	struct xinpgen *xig, *exig;
	struct xinpcb *xip;
	struct xtcpcb *xtp;
	struct inpcb *inp;
	void *buf = NULL;
	size_t len;

	switch (proto) {
	case IPPROTO_TCP:
		varname = "net.inet.tcp.pcblist";
		break;
	case IPPROTO_UDP:
		varname = "net.inet.udp.pcblist";
		break;
	default:
		syslog(LOG_ERR, "port_in_use() unknown proto=%d", proto);
		return -1;
	}

	if (sysctlbyname(varname, NULL, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, NULL, ...): %m", varname);
		return -1;
	}
	buf = malloc(len);
	if (buf == NULL) {
		syslog(LOG_ERR, "malloc(%u) failed", (unsigned)len);
		return -1;
	}
	if (sysctlbyname(varname, buf, &len, NULL, 0) < 0) {
		syslog(LOG_ERR, "sysctlbyname(%s, buf, ...): %m", varname);
		free(buf);
		return -1;
	}

	xig = (struct xinpgen *)buf;
	exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig);
	if (xig->xig_len != sizeof *xig) {
		syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld",
		       (long)xig->xig_len, sizeof *xig);
		free(buf);
		return -1;
	}
	if (exig->xig_len != sizeof *exig) {
		syslog(LOG_WARNING, "struct xinpgen size mismatch; %ld vs %ld",
		       (long)exig->xig_len, sizeof *exig);
		free(buf);
		return -1;
	}

	while (1) {
		xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
		if (xig >= exig)
			break;
		switch (proto) {
		case IPPROTO_TCP:
			xtp = (struct xtcpcb *)xig;
			if (xtp->xt_len != sizeof *xtp) {
				syslog(LOG_WARNING, "struct xtcpcb size mismatch; %ld vs %ld",
				       (long)xtp->xt_len, sizeof *xtp);
				free(buf);
				return -1;
			}
			inp = &xtp->xt_inp;
			break;
		case IPPROTO_UDP:
			xip = (struct xinpcb *)xig;
			if (xip->xi_len != sizeof *xip) {
				syslog(LOG_WARNING, "struct xinpcb size mismatch : %ld vs %ld",
				       (long)xip->xi_len, sizeof *xip);
				free(buf);
				return -1;
			}
			inp = &xip->xi_inp;
			break;
		default:
			abort();
		}
		/* no support for IPv6 */
		if ((inp->inp_vflag & INP_IPV6) != 0)
			continue;
		syslog(LOG_DEBUG, "%08lx:%hu %08lx:%hu <=> %hu %08lx:%hu",
		       (u_long)inp->inp_laddr.s_addr, ntohs(inp->inp_lport),
		       (u_long)inp->inp_faddr.s_addr, ntohs(inp->inp_fport),
		       eport, (u_long)ip_addr.s_addr, iport
		);
		if (eport == (unsigned)ntohs(inp->inp_lport)) {
			if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_laddr.s_addr == ip_addr.s_addr) {
				found++;
				break;  /* don't care how many, just that we found at least one */
			}
		}
	}
	if (buf) {
		free(buf);
		buf = NULL;
	}
/* #elif __NetBSD__ */
#else
/* TODO : NetBSD / Darwin (OS X) / Solaris code */
#error "No port_in_use() implementation available for this OS"
#endif

	/* Phase 2 : check existing mappings
	 * TODO : implement for pf/ipfw/etc. */
#if defined(USE_NETFILTER)
	if (!found) {
		char iaddr_old[16];
		unsigned short iport_old;
		int i;
		for (i = 0; chains_to_check[i]; i++) {
			if (get_nat_redirect_rule(chains_to_check[i], if_name, eport, proto,
					iaddr_old, sizeof(iaddr_old), &iport_old,
					0, 0, 0, 0, 0, 0, 0) == 0)
			{
				syslog(LOG_DEBUG, "port_in_use check port %d on nat chain %s redirected to %s port %d", eport,
						chains_to_check[i], iaddr_old, iport_old);
				if (!(strcmp(iaddr, iaddr_old)==0 && iport==iport_old)) {
					/* only "in use" if redirected to somewhere else */
					found++;
					break;  /* don't care how many, just that we found at least one */
				}
			}
		}
	}
#else /* USE_NETFILTER */
	UNUSED(iport); UNUSED(iaddr);
#endif /* USE_NETFILTER */
	return found;
}