/* * Handle an incoming RIP packet. */ static void rip_input(struct sockaddr_in *from, int size, uint_t ifindex) { struct netinfo *n, *lim; struct in_addr in; const char *name; char net_buf[80]; uchar_t hash[RIP_AUTH_MD5_LEN]; MD5_CTX md5_ctx; uchar_t md5_authed = 0; in_addr_t mask, dmask; struct in_addr tmp_addr; char *sp; char ifname[IF_NAMESIZE+1]; int i; struct hostent *hp; struct netent *np; struct netauth *na; char srcaddr[MAXHOSTNAMELEN + sizeof (" (123.123.123.123)") + 1]; char ifstring[IF_NAMESIZE + 3*sizeof (ifindex) + sizeof (" ()") + 1]; if (!nflag && (hp = gethostbyaddr((char *)&from->sin_addr, sizeof (struct in_addr), AF_INET)) != NULL) { (void) snprintf(srcaddr, sizeof (srcaddr), "%s (%s)", hp->h_name, inet_ntoa(from->sin_addr)); } else { /* safe; cannot overflow destination */ (void) strcpy(srcaddr, inet_ntoa(from->sin_addr)); } if (ifindex == 0) { (void) printf("%s:", srcaddr); } else { if (if_indextoname(ifindex, ifname) != NULL) (void) snprintf(ifstring, sizeof (ifstring), "%s (%d)", ifname, ifindex); else (void) snprintf(ifstring, sizeof (ifstring), "%d", ifindex); (void) printf(gettext("%1$s received on interface %2$s:"), srcaddr, ifstring); } if (IMSG.rip_cmd != RIPCMD_RESPONSE) { (void) printf(gettext("\n unexpected response type %d\n"), IMSG.rip_cmd); return; } (void) printf(gettext(" RIPv%1$d%2$s %3$d bytes\n"), IMSG.rip_vers, (IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "", size); if (size > MAXPACKETSIZE) { if (size > sizeof (imsg_buf) - sizeof (*n)) { (void) printf( gettext(" at least %d bytes too long\n"), size-MAXPACKETSIZE); size = sizeof (imsg_buf) - sizeof (*n); } else { (void) printf(gettext(" %d bytes too long\n"), size-MAXPACKETSIZE); } } else if (size%sizeof (*n) != sizeof (struct rip)%sizeof (*n)) { (void) printf(gettext(" response of bad length=%d\n"), size); } n = IMSG.rip_nets; lim = n + (size - 4) / sizeof (struct netinfo); for (; n < lim; n++) { name = ""; if (n->n_family == RIP_AF_INET) { in.s_addr = n->n_dst; (void) strlcpy(net_buf, inet_ntoa(in), sizeof (net_buf)); tmp_addr.s_addr = (n->n_mask); mask = ntohl(n->n_mask); dmask = mask & -mask; if (mask != 0) { sp = &net_buf[strlen(net_buf)]; if (IMSG.rip_vers == RIPv1) { (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), gettext(" mask=%s ? "), inet_ntoa(tmp_addr)); mask = 0; } else if (mask + dmask == 0) { i = ffs(mask) - 1; (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), "/%d", 32-i); } else { (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), gettext(" (mask %s)"), inet_ntoa(tmp_addr)); } } if (!nflag) { if (mask == 0) { mask = std_mask(in.s_addr); if ((ntohl(in.s_addr) & ~mask) != 0) mask = 0; } /* * Without a netmask, do not worry about * whether the destination is a host or a * network. Try both and use the first name * we get. * * If we have a netmask we can make a * good guess. */ if ((in.s_addr & ~mask) == 0) { np = getnetbyaddr((long)in.s_addr, AF_INET); if (np != NULL) name = np->n_name; else if (in.s_addr == 0) name = "default"; } if (name[0] == '\0' && ((in.s_addr & ~mask) != 0 || mask == 0xffffffff)) { hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); if (hp != NULL) name = hp->h_name; } } } else if (n->n_family == RIP_AF_AUTH) { na = (struct netauth *)n; if (na->a_type == RIP_AUTH_PW && n == IMSG.rip_nets) { (void) printf( gettext(" Password Authentication:" " \"%s\"\n"), qstring(na->au.au_pw, RIP_AUTH_PW_LEN)); continue; } if (na->a_type == RIP_AUTH_MD5 && n == IMSG.rip_nets) { (void) printf(gettext(" MD5 Auth" " len=%1$d KeyID=%2$d" " auth_len=%3$d" " seqno=%4$#x" " rsvd=%5$#x,%6$#x\n"), ntohs(na->au.a_md5.md5_pkt_len), na->au.a_md5.md5_keyid, na->au.a_md5.md5_auth_len, (int)ntohl(na->au.a_md5.md5_seqno), na->au.a_md5.rsvd[0], na->au.a_md5.rsvd[1]); md5_authed = 1; continue; } (void) printf(gettext(" Authentication type %d: "), ntohs(na->a_type)); for (i = 0; i < sizeof (na->au.au_pw); i++) (void) printf("%02x ", na->au.au_pw[i]); (void) putchar('\n'); if (md5_authed && n+1 > lim && na->a_type == RIP_AUTH_TRAILER) { MD5Init(&md5_ctx); MD5Update(&md5_ctx, (uchar_t *)&IMSG, (char *)na-(char *)&IMSG); MD5Update(&md5_ctx, (uchar_t *)passwd, RIP_AUTH_MD5_LEN); MD5Final(hash, &md5_ctx); (void) printf(gettext(" %s hash\n"), memcmp(hash, na->au.au_pw, sizeof (hash)) ? gettext("WRONG") : gettext("correct")); } else if (md5_authed && n+1 > lim && na->a_type != RIP_AUTH_TRAILER) { (void) printf(gettext("Error -" "authentication entry missing hash\n")); } continue; } else { tmp_addr.s_addr = n->n_dst; (void) snprintf(net_buf, sizeof (net_buf), gettext("(address family %1$u) %2$s"), ntohs(n->n_family), inet_ntoa(tmp_addr)); } (void) printf(gettext(" %1$-18s metric %2$2lu %3$-10s"), net_buf, ntohl(n->n_metric), name); if (n->n_nhop != 0) { in.s_addr = n->n_nhop; if (nflag) hp = NULL; else hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); (void) printf(gettext(" nhop=%1$-15s%2$s"), (hp != NULL) ? hp->h_name : inet_ntoa(in), (IMSG.rip_vers == RIPv1) ? " ?" : ""); } if (n->n_tag != 0) (void) printf(gettext(" tag=%1$#x%2$s"), n->n_tag, (IMSG.rip_vers == RIPv1) ? " ?" : ""); (void) putchar('\n'); } }
static int INET_rresolve(char *name, struct sockaddr_in *sin, int numeric, unsigned int netmask) { struct hostent *ent; struct netent *np; struct addr *pn; unsigned long ad, host_ad; /* Grmpf. -FvK */ if (sin->sin_family != AF_INET) { #ifdef DEBUG fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family); #endif errno = EAFNOSUPPORT; return (-1); } ad = (unsigned long) sin->sin_addr.s_addr; if (ad == INADDR_ANY) { if ((numeric & 0x7FFF) == 0) { if (numeric & 0x8000) strcpy(name, "default"); else strcpy(name, "*"); return (0); } } if (numeric & 0x7FFF) { strcpy(name, inet_ntoa(sin->sin_addr)); return (0); } #if 0 INET_nn = NULL; #endif pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad) { strcpy(name, pn->name); return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; #ifndef EMBED if ((ad & (~ netmask)) != 0) { ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) strcpy(name, ent->h_name); } else { np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) { strcpy(name, np->n_name); } } #endif if ((ent == NULL) && (np == NULL)) { strcpy(name, inet_ntoa(sin->sin_addr)); } pn = (struct addr *) malloc(sizeof(struct addr)); pn->addr = *sin; pn->next = INET_nn; pn->name = (char *) malloc(strlen(name) + 1); strcpy(pn->name, name); INET_nn = pn; return (0); }
/* * Construct an Internet address representation. * If the nflag has been supplied, give * numeric value, otherwise try for symbolic name. */ char * inetname(struct in_addr *inp) { char *cp; static char line[50]; struct hostent *hp; struct netent *np; static char domain[MAXHOSTNAMELEN]; static int first = 1; #if defined (WIN32) || defined (cygwin) char host_temp[] = "localhost"; #endif if (first && !nflag) { first = 0; if (gethostname(domain, sizeof(domain)) == 0 && (cp = strchr(domain, '.'))) (void) strlcpy(domain, cp + 1, sizeof domain); else domain[0] = '\0'; } cp = NULL; if (!nflag && inp->s_addr != INADDR_ANY) { int net = inet_netof(*inp); int lna = inet_lnaof(*inp); if (lna == INADDR_ANY) { np = getnetbyaddr(net, AF_INET); if (np) cp = np->n_name; } if (cp == NULL) { hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); if (hp) { if ((cp = strchr(hp->h_name, '.')) && !strcmp(cp + 1, domain)) *cp = '\0'; #if defined (WIN32) || defined (cygwin) /* Windows insists on returning the computer name for 127.0.0.1 * even if the hosts file lists something else such as 'localhost'. * If we are trying to look up 127.0.0.1, just return 'localhost' */ if (!strcmp(inet_ntoa(*inp),"127.0.0.1")) cp = host_temp; else #endif cp = hp->h_name; } } } if (inp->s_addr == INADDR_ANY) snprintf(line, sizeof line, "*"); else if (cp) snprintf(line, sizeof line, "%s", cp); else { inp->s_addr = ntohl(inp->s_addr); #define C(x) ((x) & 0xff) snprintf(line, sizeof line, "%u.%u.%u.%u", C(inp->s_addr >> 24), C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); } return (line); }
/* numeric: & 0x8000: default instead of *, * & 0x4000: host instead of net, * & 0x0fff: don't resolve */ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, int numeric, unsigned int netmask) { struct hostent *ent; struct netent *np; struct addr *pn; unsigned long ad, host_ad; int host = 0; /* Grmpf. -FvK */ if (s_in->sin_family != AF_INET) { errno = EAFNOSUPPORT; return (-1); } ad = (unsigned long) s_in->sin_addr.s_addr; if (ad == INADDR_ANY) { if ((numeric & 0x0FFF) == 0) { if (numeric & 0x8000) safe_strncpy(name,"default", len); else safe_strncpy(name, "*", len); return (0); } } if (numeric & 0x0FFF) { safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); return (0); } if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) host = 1; #if 0 INET_nn = NULL; #endif pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { safe_strncpy(name, pn->name, len); return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; if (host) { ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) { safe_strncpy(name, ent->h_name, len); } } else { np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) { safe_strncpy(name, np->n_name, len); } } if ((ent == NULL) && (np == NULL)) { safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); } pn = (struct addr *) xmalloc(sizeof(struct addr)); pn->addr = *s_in; pn->next = INET_nn; pn->host = host; pn->name = strdup(name); INET_nn = pn; return (0); }
/* numeric: & 0x8000: default instead of *, * & 0x4000: host instead of net, * & 0x0fff: don't resolve */ static int INET_rresolve(char *name, size_t len, const struct sockaddr_storage *sasp, int numeric, unsigned int netmask) { const struct sockaddr_in *sin = (const struct sockaddr_in *)sasp; struct hostent *ent; struct netent *np; struct addr *pn; u_int32_t ad, host_ad; int host = 0; /* Grmpf. -FvK */ if (sin->sin_family != AF_INET) { #ifdef DEBUG fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family); #endif errno = EAFNOSUPPORT; return (-1); } ad = sin->sin_addr.s_addr; #ifdef DEBUG fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x, len %d\n", ad, netmask, numeric, len); #endif // if no symbolic names are requested we shortcut with ntoa if (numeric & 0x0FFF) { safe_strncpy(name, inet_ntoa(sin->sin_addr), len); return (0); } // we skip getnetbyaddr for 0.0.0.0/0 and 0.0.0.0/~0 if (ad == INADDR_ANY) { if (netmask == INADDR_ANY) { // for 0.0.0.0/0 we hardcode symbolic name if (numeric & 0x8000) safe_strncpy(name, "default", len); else safe_strncpy(name, "*", len); return (0); } else { // for 0.0.0.0/1 we skip getnetbyname() safe_strncpy(name, "0.0.0.0", len); return (0); } } // it is a host address if flagged or any host bits set if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) host = 1; #if 0 INET_nn = NULL; #endif pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { safe_strncpy(name, pn->name, len); #ifdef DEBUG fprintf (stderr, "rresolve: found %s %08lx in cache (name=%s, len=%d)\n", (host? "host": "net"), ad, name, len); #endif return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; if (host) { #ifdef DEBUG fprintf (stderr, "gethostbyaddr (%08lx)\n", ad); #endif ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) safe_strncpy(name, ent->h_name, len); } else { #ifdef DEBUG fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad); #endif np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) safe_strncpy(name, np->n_name, len); } if ((ent == NULL) && (np == NULL)) safe_strncpy(name, inet_ntoa(sin->sin_addr), len); pn = (struct addr *) xmalloc(sizeof(struct addr)); pn->addr = *sin; pn->next = INET_nn; pn->host = host; pn->name = xstrdup(name); INET_nn = pn; return (0); }
/* numeric: & 0x8000: default instead of *, * & 0x4000: host instead of net, * & 0x0fff: don't resolve */ int INET_rresolve(char *name, size_t len, struct sockaddr_in *s_in, int numeric, unsigned int netmask) { struct hostent *ent; struct netent *np; struct addr *pn; unsigned long ad, host_ad; int host = 0; /* Grmpf. -FvK */ if (s_in->sin_family != AF_INET) { #ifdef DEBUG bb_error_msg("rresolve: unsupport address family %d !", s_in->sin_family); #endif errno = EAFNOSUPPORT; return (-1); } ad = (unsigned long) s_in->sin_addr.s_addr; #ifdef DEBUG bb_error_msg("rresolve: %08lx, mask %08x, num %08x", ad, netmask, numeric); #endif if (ad == INADDR_ANY) { if ((numeric & 0x0FFF) == 0) { if (numeric & 0x8000) safe_strncpy(name, bb_INET_default, len); else safe_strncpy(name, "*", len); return (0); } } if (numeric & 0x0FFF) { safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); return (0); } if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) host = 1; #if 0 INET_nn = NULL; #endif pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { safe_strncpy(name, pn->name, len); #ifdef DEBUG bb_error_msg("rresolve: found %s %08lx in cache", (host ? "host" : "net"), ad); #endif return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; if (host) { #ifdef DEBUG bb_error_msg("gethostbyaddr (%08lx)", ad); #endif ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) { safe_strncpy(name, ent->h_name, len); } } else { #ifdef DEBUG bb_error_msg("getnetbyaddr (%08lx)", host_ad); #endif np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) { safe_strncpy(name, np->n_name, len); } } if ((ent == NULL) && (np == NULL)) { safe_strncpy(name, inet_ntoa(s_in->sin_addr), len); } pn = (struct addr *) xmalloc(sizeof(struct addr)); pn->addr = *s_in; pn->next = INET_nn; pn->host = host; pn->name = bb_xstrdup(name); INET_nn = pn; return (0); }
void rip_input(struct sockaddr *sa, int size) { struct sockaddr_in *from = (struct sockaddr_in *)sa; register struct rip *msg = (struct rip *)packet; register struct netinfo *n; const char *name; int lna, net, subnet; struct hostent *hp; struct netent *np; if (msg->rip_cmd != RIPCMD_RESPONSE) return; printf("%d bytes from ", size); if (nflag) printf("%s:\n", inet_ntoa(from->sin_addr)); else { hp = gethostbyaddr((char *)&from->sin_addr, sizeof (struct in_addr), AF_INET); name = hp == 0 ? "???" : hp->h_name; printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); } size -= sizeof (int); n = msg->rip_nets; while (size > 0) { if (size < (int)sizeof (struct netinfo)) break; if (msg->rip_vers > 0) { n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); n->rip_metric = ntohl(n->rip_metric); } switch (n->rip_dst.sa_family) { case AF_INET: { register struct sockaddr_in *sin; sin = (struct sockaddr_in *)&n->rip_dst; net = inet_netof(sin->sin_addr); subnet = inet_subnetof(sin->sin_addr); lna = inet_lnaof(sin->sin_addr); name = "???"; if (!nflag) { if (sin->sin_addr.s_addr == 0) name = "default"; else if (lna == INADDR_ANY) { np = getnetbyaddr(net, AF_INET); if (np) name = np->n_name; else if (net == 0) name = "default"; } else if ((lna & 0xff) == 0 && (np = getnetbyaddr(subnet, AF_INET))) { struct in_addr subnaddr; subnaddr = inet_makeaddr(subnet, INADDR_ANY); if (memcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) name = np->n_name; else goto host; } else { host: hp = gethostbyaddr((char *)&sin->sin_addr, sizeof (struct in_addr), AF_INET); if (hp) name = hp->h_name; } printf("\t%-17s metric %2d name %s\n", inet_ntoa(sin->sin_addr), n->rip_metric, name); } else printf("\t%-17s metric %2d\n", inet_ntoa(sin->sin_addr), n->rip_metric); break; } default: { u_short *p = (u_short *)n->rip_dst.sa_data; printf("\t(af %d) %x %x %x %x %x %x %x, metric %d\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], n->rip_dst.sa_family, n->rip_metric); break; } } size -= sizeof (struct netinfo), n++; } }