This commit was generated by cvs2svn to compensate for changes in r42888,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Bill Fenner 1999-01-20 07:44:18 +00:00
commit b8d4f311c5
4 changed files with 413 additions and 0 deletions

1
usr.sbin/mrouted/VERSION Normal file
View File

@ -0,0 +1 @@
3.9-beta3+IOS12

225
usr.sbin/mrouted/icmp.c Normal file
View File

@ -0,0 +1,225 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp
*/
#include "defs.h"
#ifndef lint
static char rcsid[] = "@(#) $Id: \
icmp.c,v 3.8.4.2 1998/01/06 01:57:42 fenner Exp $";
#endif
static int icmp_socket;
static void icmp_handler __P((int, fd_set *));
static char * icmp_name __P((struct icmp *));
void
init_icmp()
{
if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
log(LOG_ERR, errno, "ICMP socket");
register_input_handler(icmp_socket, icmp_handler);
IF_DEBUG(DEBUG_ICMP)
log(LOG_DEBUG, 0, "registering icmp socket fd %d\n", icmp_socket);
}
static void
icmp_handler(fd, rfds)
int fd;
fd_set *rfds;
{
u_char icmp_buf[RECV_BUF_SIZE];
struct sockaddr_in from;
int fromlen, recvlen, iphdrlen, ipdatalen;
struct icmp *icmp;
struct ip *ip;
vifi_t i;
struct uvif *v;
u_int32 src;
fromlen = sizeof(from);
recvlen = recvfrom(icmp_socket, icmp_buf, RECV_BUF_SIZE, 0,
(struct sockaddr *)&from, &fromlen);
if (recvlen < 0) {
if (errno != EINTR)
log(LOG_WARNING, errno, "icmp_socket recvfrom");
return;
}
ip = (struct ip *)icmp_buf;
iphdrlen = ip->ip_hl << 2;
#ifdef RAW_INPUT_IS_RAW
ipdatalen = ntohs(ip->ip_len) - iphdrlen;
#else
ipdatalen = ip->ip_len;
#endif
if (iphdrlen + ipdatalen != recvlen) {
IF_DEBUG(DEBUG_ICMP)
log(LOG_DEBUG, 0, "hdr %d data %d != rcv %d", iphdrlen, ipdatalen, recvlen);
/* Malformed ICMP, just return. */
return;
}
if (ipdatalen < ICMP_MINLEN + sizeof(struct ip)) {
/* Not enough data for us to be interested in it. */
return;
}
src = ip->ip_src.s_addr;
icmp = (struct icmp *)(icmp_buf + iphdrlen);
IF_DEBUG(DEBUG_ICMP)
log(LOG_DEBUG, 0, "got ICMP type %d from %s",
icmp->icmp_type, inet_fmt(src, s1));
/*
* Eventually:
* have registry of ICMP listeners, by type, code and ICMP_ID
* (and maybe fields of the original packet too -- maybe need a
* generalized packet filter!) to allow ping and traceroute
* from the monitoring tool.
*/
switch (icmp->icmp_type) {
case ICMP_UNREACH:
case ICMP_TIMXCEED:
/* Look at returned packet to see if it's us sending on a tunnel */
ip = &icmp->icmp_ip;
if (ip->ip_p != IPPROTO_IGMP && ip->ip_p != IPPROTO_IPIP)
return;
for (v = uvifs, i = 0; i < numvifs; v++, i++) {
if (ip->ip_src.s_addr == v->uv_lcl_addr &&
ip->ip_dst.s_addr == v->uv_dst_addr) {
char *p;
int n;
/*
* I sent this packet on this vif.
*/
n = ++v->uv_icmp_warn;
while (n && !(n & 1))
n >>= 1;
if (n == 1 && ((p = icmp_name(icmp)) != NULL))
log(LOG_WARNING, 0, "Received ICMP %s from %s %s %s on vif %d",
p, inet_fmt(src, s1), "for traffic sent to",
inet_fmt(ip->ip_dst.s_addr, s2),
i);
break;
}
}
break;
}
}
/*
* Return NULL for ICMP informational messages.
* Return string describing the error for ICMP errors.
*/
static char *
icmp_name(icmp)
struct icmp *icmp;
{
static char retval[30];
switch (icmp->icmp_type) {
case ICMP_UNREACH:
switch (icmp->icmp_code) {
case ICMP_UNREACH_NET:
return "network unreachable";
case ICMP_UNREACH_HOST:
return "host unreachable";
case ICMP_UNREACH_PROTOCOL:
return "protocol unreachable";
case ICMP_UNREACH_PORT:
return "port unreachable";
case ICMP_UNREACH_NEEDFRAG:
return "needs fragmentation";
case ICMP_UNREACH_SRCFAIL:
return "source route failed";
#ifndef ICMP_UNREACH_NET_UNKNOWN
#define ICMP_UNREACH_NET_UNKNOWN 6
#endif
case ICMP_UNREACH_NET_UNKNOWN:
return "network unknown";
#ifndef ICMP_UNREACH_HOST_UNKNOWN
#define ICMP_UNREACH_HOST_UNKNOWN 7
#endif
case ICMP_UNREACH_HOST_UNKNOWN:
return "host unknown";
#ifndef ICMP_UNREACH_ISOLATED
#define ICMP_UNREACH_ISOLATED 8
#endif
case ICMP_UNREACH_ISOLATED:
return "source host isolated";
#ifndef ICMP_UNREACH_NET_PROHIB
#define ICMP_UNREACH_NET_PROHIB 9
#endif
case ICMP_UNREACH_NET_PROHIB:
return "network access prohibited";
#ifndef ICMP_UNREACH_HOST_PROHIB
#define ICMP_UNREACH_HOST_PROHIB 10
#endif
case ICMP_UNREACH_HOST_PROHIB:
return "host access prohibited";
#ifndef ICMP_UNREACH_TOSNET
#define ICMP_UNREACH_TOSNET 11
#endif
case ICMP_UNREACH_TOSNET:
return "bad TOS for net";
#ifndef ICMP_UNREACH_TOSHOST
#define ICMP_UNREACH_TOSHOST 12
#endif
case ICMP_UNREACH_TOSHOST:
return "bad TOS for host";
#ifndef ICMP_UNREACH_FILTER_PROHIB
#define ICMP_UNREACH_FILTER_PROHIB 13
#endif
case ICMP_UNREACH_FILTER_PROHIB:
return "prohibited by filter";
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
#define ICMP_UNREACH_HOST_PRECEDENCE 14
#endif
case ICMP_UNREACH_HOST_PRECEDENCE:
return "host precedence violation";
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
#endif
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
return "precedence cutoff";
default:
sprintf(retval, "unreachable code %d", icmp->icmp_code);
return retval;
}
case ICMP_SOURCEQUENCH:
return "source quench";
case ICMP_REDIRECT:
return NULL; /* XXX */
case ICMP_TIMXCEED:
switch (icmp->icmp_code) {
case ICMP_TIMXCEED_INTRANS:
return "time exceeded in transit";
case ICMP_TIMXCEED_REASS:
return "time exceeded in reassembly";
default:
sprintf(retval, "time exceeded code %d", icmp->icmp_code);
return retval;
}
case ICMP_PARAMPROB:
switch (icmp->icmp_code) {
#ifndef ICMP_PARAMPROB_OPTABSENT
#define ICMP_PARAMPROB_OPTABSENT 1
#endif
case ICMP_PARAMPROB_OPTABSENT:
return "required option absent";
default:
sprintf(retval, "parameter problem code %d", icmp->icmp_code);
return retval;
}
}
return NULL;
}

42
usr.sbin/mrouted/igmpv2.h Normal file
View File

@ -0,0 +1,42 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* igmpv2.h,v 3.8.4.1 1997/11/18 23:25:58 fenner Exp
*/
/*
* Constants for IGMP Version 2. Several of these, especially the
* robustness variable, should be variables and not constants.
*/
#define IGMP_ROBUSTNESS_VARIABLE 2
#define IGMP_QUERY_INTERVAL 125
#define IGMP_QUERY_RESPONSE_INTERVAL 10
#define IGMP_GROUP_MEMBERSHIP_INTERVAL (IGMP_ROBUSTNESS_VARIABLE * \
IGMP_QUERY_INTERVAL + \
IGMP_QUERY_RESPONSE_INTERVAL)
#define IGMP_OTHER_QUERIER_PRESENT_INTERVAL (IGMP_ROBUSTNESS_VARIABLE * \
IGMP_QUERY_INTERVAL + \
IGMP_QUERY_RESPONSE_INTERVAL / 2)
/* Round to the nearest TIMER_INTERVAL */
#define IGMP_STARTUP_QUERY_INTERVAL (((IGMP_QUERY_INTERVAL / 4) \
/ TIMER_INTERVAL) * TIMER_INTERVAL)
#define IGMP_STARTUP_QUERY_COUNT IGMP_ROBUSTNESS_VARIABLE
#define IGMP_LAST_MEMBER_QUERY_INTERVAL 1
#define IGMP_LAST_MEMBER_QUERY_COUNT IGMP_ROBUSTNESS_VARIABLE
/*
* OLD_AGE_THRESHOLD is the number of IGMP_QUERY_INTERVAL's to remember the
* presence of an IGMPv1 group member. According to the IGMPv2 specification,
* routers remember this presence for [Robustness Variable] * [Query Interval] +
* [Query Response Interval]. However, OLD_AGE_THRESHOLD is in units of
* [Query Interval], so doesn't have sufficient resolution to represent
* [Query Response Interval]. When the timer mechanism gets an efficient
* method of refreshing timers, this should get fixed.
*/
#define OLD_AGE_THRESHOLD IGMP_ROBUSTNESS_VARIABLE

145
usr.sbin/mrouted/ipip.c Normal file
View File

@ -0,0 +1,145 @@
/*
* The mrouted program is covered by the license in the accompanying file
* named "LICENSE". Use of the mrouted program represents acceptance of
* the terms and conditions listed in that file.
*
* The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
* Leland Stanford Junior University.
*
*
* ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp
*/
#include "defs.h"
#ifndef lint
static char rcsid[] = "@(#) $Id: \
ipip.c,v 3.8.4.6 1998/01/06 01:57:45 fenner Exp $";
#endif
/*
* Exported variables.
*/
#ifdef notyet
int raw_socket; /* socket for raw network I/O */
#endif
/*
*XXX For now, we just use the IGMP socket to send packets.
* This is legal in BSD, because the protocol # is not checked
* on raw sockets. The k_* interfaces need to gain a socket
* argument so that we can call them on the raw_socket also.
*/
#define raw_socket igmp_socket
/*
* Private variables.
*/
static int rawid = 0;
/*
* Open and initialize the raw socket.
*/
void
init_ipip()
{
#ifdef notyet
if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
log(LOG_ERR, errno, "Raw IP socket");
#endif
}
/*
* Allocate and fill in static IP header for encapsulating on a tunnel.
*/
void
init_ipip_on_vif(v)
struct uvif *v;
{
struct ip *ip;
ip = v->uv_encap_hdr = (struct ip *)malloc(sizeof(struct ip));
if (ip == NULL)
log(LOG_ERR, 0, "out of memory");
bzero(ip, sizeof(struct ip));
/*
* Fields zeroed that aren't filled in later:
* - IP ID (let the kernel fill it in)
* - Offset (we don't send fragments)
* - Checksum (let the kernel fill it in)
*/
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip) >> 2;
ip->ip_tos = 0xc0; /* Internet Control */
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
ip->ip_p = IPPROTO_IPIP;
ip->ip_src.s_addr = v->uv_lcl_addr;
ip->ip_dst.s_addr = v->uv_rmt_addr;
}
/*
* Call build_igmp() to build an IGMP message in the output packet buffer.
* Then fill in the fields of the IP packet that build_igmp() left for the
* kernel to fill in, and encapsulate the original packet with the
* pre-created ip header for this vif.
*/
void
send_ipip(src, dst, type, code, group, datalen, v)
u_int32 src, dst;
int type, code;
u_int32 group;
int datalen;
struct uvif *v;
{
struct msghdr msg;
struct iovec iov[2];
struct sockaddr_in sdst;
struct ip *ip;
build_igmp(src, dst, type, code, group, datalen);
ip = (struct ip *)send_buf;
#ifndef RAW_OUTPUT_IS_RAW
ip->ip_len = htons(ip->ip_len);
#endif
ip->ip_id = htons(rawid++);
ip->ip_sum = 0;
ip->ip_sum = inet_cksum((u_short *)ip, ip->ip_hl << 2);
ip = v->uv_encap_hdr;
ip->ip_len = 2 * MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
#ifdef RAW_OUTPUT_IS_RAW
ip->ip_len = htons(ip->ip_len);
#endif
bzero(&sdst, sizeof(sdst));
sdst.sin_family = AF_INET;
#ifdef HAVE_SA_LEN
sdst.sin_len = sizeof(sdst);
#endif
sdst.sin_addr = ip->ip_dst;
iov[0].iov_base = (caddr_t)v->uv_encap_hdr;
iov[0].iov_len = sizeof(struct ip);
iov[1].iov_base = (caddr_t)send_buf;
iov[1].iov_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen;
bzero(&msg, sizeof(msg));
msg.msg_name = (caddr_t)&sdst;
msg.msg_namelen = sizeof(sdst);
msg.msg_iov = iov;
msg.msg_iovlen = 2;
if (sendmsg(raw_socket, &msg, 0) < 0) {
if (errno == ENETDOWN)
check_vif_state();
else
log(LOG_WARNING, errno,
"sendmsg to %s on %s",
inet_fmt(sdst.sin_addr.s_addr, s1), inet_fmt(src, s2));
}
IF_DEBUG(DEBUG_PKT|igmp_debug_kind(type, code))
log(LOG_DEBUG, 0, "SENT %s from %-15s to %s encaped to %s",
igmp_packet_kind(type, code), src == INADDR_ANY ? "INADDR_ANY" :
inet_fmt(src, s1), inet_fmt(dst, s2),
inet_fmt(sdst.sin_addr.s_addr, s3));
}