2021-10-11 18:37:13 -03:00

328 lines
6.7 KiB
C

/*
* IP Utility module for the "Etherfind" program
*
* @(#)ip.c 1.1 94/10/31
*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/udp_var.h>
#include <netinet/ip_icmp.h>
extern unsigned long inet_network();
extern unsigned long inet_addr();
extern char *malloc(), *index();
#define ICMPTABLESIZE 256
char *icmptable[ICMPTABLESIZE];
extern int nflag;
#define HASHNAMESIZE 256
/*
* XXX: Need to revise to take multiple addresses per interface
* into account. This change should be part of a revision
* that teaches etherfind about protocol families other than
* AF_INET.
*/
struct hnamemem {
struct in_addr h_addr0; /* first address in list (XXX) */
char *h_name;
struct hnamemem *h_nxt;
};
struct hnamemem *htable[HASHNAMESIZE];
#define TCP 0
#define UDP 1
#define NPROTOCOLS 2
#define MAXPORT 1024
char *names[NPROTOCOLS][MAXPORT];
#define PROTOTABLESIZE 256
char *prototable[PROTOTABLESIZE];
/*
* return the name of the given IP address, using the internal hash
* table if necessary. The "nflag" bypasses all name lookup and just
* prints it out as a number. The address is passed as a structure in
* network order.
*/
char *
getname(addr)
struct in_addr addr;
{
int x;
struct hnamemem *p;
char *buf, *inet_ntoa();
struct netent *np;
struct hostent *hp;
x = ntohl(addr.s_addr) & 0xff;
for (p = htable[x]; p != NULL; p = p->h_nxt) {
if (p->h_addr0.s_addr == addr.s_addr)
return (p->h_name);
}
p = (struct hnamemem *)malloc(sizeof(struct hnamemem));
p->h_addr0 = addr;
p->h_nxt = htable[x];
htable[x] = p;
# ifndef INADDR_BROADCAST
# define INADDR_BROADCAST (0xffffffff)
# endif
if (nflag) {
hp = NULL;
}
else {
if (addr.s_addr == htonl(INADDR_BROADCAST)) {
p->h_name = "broadcast";
return (p->h_name);
}
if (addr.s_addr == htonl(INADDR_ANY)) {
p->h_name = "old-broadcast";
return (p->h_name);
}
hp = gethostbyaddr((char *)&addr, sizeof(int), AF_INET);
if (hp == NULL && inet_lnaof(addr) == 0) {
np = getnetbyaddr(inet_netof(addr), AF_INET);
if (np) {
p->h_name = malloc((unsigned)strlen(np->n_name) + 1);
(void) strcpy(p->h_name, np->n_name);
return (p->h_name);
}
}
}
if (hp) {
p->h_name = malloc((unsigned)strlen(hp->h_name) + 1);
(void) strcpy(p->h_name, hp->h_name);
}
else {
buf = inet_ntoa(addr);
p->h_name = malloc((unsigned)(strlen(buf)) + 1);
(void) strcpy(p->h_name, buf);
}
return (p->h_name);
}
/*
* convert string (which may be host address or host name) to address
*/
stringtoaddr(name)
char *name;
{
struct hostent *hp;
char *p;
unsigned short a, b;
if (isdigit(name[0])) {
p = index(name, '.');
if (p && index(p+1, '.') == 0) { /* decnet address area.host */
a = atoi(name);
b = atoi(p+1);
if ((a < 1) || (a > 63)) {
fprintf(stderr, "%d invalid decnet area\n", a);
exit(1);
}
if ((b < 1) || (b > 1023)) {
fprintf(stderr, "%d invalid decnet host\n", b);
exit(1);
}
a = (a << 10) + b;
swab((char *)&a, (char *)&b, 2);
return(b);
} else
return(inet_addr(name));
}
hp = gethostbyname(name);
if (hp == NULL) {
fprintf(stderr, "%s unknown host name\n", name);
exit(1);
}
else
return(*(int *)hp->h_addr);
}
stringtonetaddr(name)
char *name;
{
struct netent *np;
if (isdigit(name[0]))
return(inet_network(name));
np = getnetbyname(name);
if (np == NULL) {
fprintf(stderr, "%s unknown net name\n", name);
exit(1);
}
else
return (np->n_net);
}
/*
* returns the port number in Network byte order
*/
unsigned short
stringtoport(str)
char *str;
{
struct servent *sp;
if (isdigit(str[0]))
return(htons((u_short) atoi(str)));
else {
sp = getservbyname(str, (char *)NULL);
if (sp == NULL) {
fprintf(stderr,
"etherfind: %s is not a valid port name or number\n",
str);
exit(1);
}
return(sp->s_port);
}
}
/*
* Return the printable version of an IP port number
*/
char *
getportname(port, proto)
u_short port;
{
static char buf[10];
int protonum;
port = ntohs(port);
if (proto == IPPROTO_TCP)
protonum = TCP;
else if (proto == IPPROTO_UDP)
protonum = UDP;
else {
sprintf(buf, "%d", port);
return (buf);
}
if (port < MAXPORT && names[protonum][port])
return (names[protonum][port]);
else {
sprintf(buf, "%d", port);
return (buf);
}
}
char *icmptype(icp)
struct icmp *icp; /* points to icmp packet */
{
return(icmptable[icp->icmp_type]);
}
initIP()
/*
* Initialize the Internet Protocol specific module
*/
{
struct servent *sv;
int proto;
char *p;
icmptable[ICMP_ECHOREPLY] = "echo reply";
icmptable[ICMP_UNREACH] = "dst unreachable";
icmptable[ICMP_SOURCEQUENCH] = "src quench";
icmptable[ICMP_REDIRECT] = "redirect";
icmptable[ICMP_ECHO] = "echo";
icmptable[ICMP_TIMXCEED] = "time exceeded";
icmptable[ICMP_PARAMPROB] = "param problem";
icmptable[ICMP_TSTAMP] = "timestamp";
icmptable[ICMP_TSTAMPREPLY] = "timestamp reply";
icmptable[ICMP_IREQ] = "info request";
icmptable[ICMP_IREQREPLY] = "info reply";
icmptable[ICMP_MASKREQ] = "mask request";
icmptable[ICMP_MASKREPLY] = "mask reply";
for (proto = 0; proto < ICMPTABLESIZE; proto++) {
if (icmptable[proto] == NULL) {
p = malloc(5);
sprintf(p, "%d", proto);
icmptable[proto] = p;
}
}
prototable[IPPROTO_ICMP] = "icmp";
prototable[IPPROTO_IGMP] = "igmp";
prototable[IPPROTO_GGP] = "ggp";
prototable[5] = "st";
prototable[IPPROTO_TCP] = "tcp";
prototable[IPPROTO_EGP] = "egp";
prototable[IPPROTO_UDP] = "udp";
prototable[27] = "rdp";
prototable[30] = "netblt";
prototable[IPPROTO_HELLO] = "hello";
prototable[IPPROTO_ND] = "nd";
while (sv = getservent()) {
if (strcmp(sv->s_proto, "tcp") == 0)
proto = TCP;
else if (strcmp(sv->s_proto, "udp") == 0)
proto = UDP;
else
continue;
sv->s_port = ntohs(sv->s_port);
if (sv->s_port < 0 || sv->s_port >= MAXPORT)
continue;
names[proto][sv->s_port] =
malloc((unsigned)strlen(sv->s_name) + 1);
(void) strcpy(names[proto][sv->s_port], sv->s_name);
}
endservent();
}
getproto(arg)
char *arg;
{
char **p;
int protonum;
if (isalpha(arg[0])) {
protonum = -1;
for (p = prototable; p < prototable + PROTOTABLESIZE; p++) {
if (*p && strcmp(arg, *p) == 0) {
protonum = p - prototable;
break;
}
}
if (protonum == -1) {
fprintf(stderr, "%s unknown protocol\n", arg);
exit(1);
/*NOTREACHED*/
}
else
return (protonum);
}
else
return (atoi(arg));
}