summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mrouted
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>1999-01-20 07:44:18 +0000
committerfenner <fenner@FreeBSD.org>1999-01-20 07:44:18 +0000
commit1de14dda19dab2b943562326a3d97281534dc709 (patch)
tree1c9b4b17b922c10898da57f8415b0588b380bacf /usr.sbin/mrouted
parent00736ae9131bddd05cf204fdd53a52aaf79adf63 (diff)
parent2985169d50e66395695b97df6a39aea40f2aef64 (diff)
downloadFreeBSD-src-1de14dda19dab2b943562326a3d97281534dc709.zip
FreeBSD-src-1de14dda19dab2b943562326a3d97281534dc709.tar.gz
This commit was generated by cvs2svn to compensate for changes in r42888,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'usr.sbin/mrouted')
-rw-r--r--usr.sbin/mrouted/VERSION1
-rw-r--r--usr.sbin/mrouted/icmp.c225
-rw-r--r--usr.sbin/mrouted/igmpv2.h42
-rw-r--r--usr.sbin/mrouted/ipip.c145
4 files changed, 413 insertions, 0 deletions
diff --git a/usr.sbin/mrouted/VERSION b/usr.sbin/mrouted/VERSION
new file mode 100644
index 0000000..a0ba149
--- /dev/null
+++ b/usr.sbin/mrouted/VERSION
@@ -0,0 +1 @@
+3.9-beta3+IOS12
diff --git a/usr.sbin/mrouted/icmp.c b/usr.sbin/mrouted/icmp.c
new file mode 100644
index 0000000..72efa0a
--- /dev/null
+++ b/usr.sbin/mrouted/icmp.c
@@ -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;
+}
diff --git a/usr.sbin/mrouted/igmpv2.h b/usr.sbin/mrouted/igmpv2.h
new file mode 100644
index 0000000..5f5ae27
--- /dev/null
+++ b/usr.sbin/mrouted/igmpv2.h
@@ -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
diff --git a/usr.sbin/mrouted/ipip.c b/usr.sbin/mrouted/ipip.c
new file mode 100644
index 0000000..6e88d93
--- /dev/null
+++ b/usr.sbin/mrouted/ipip.c
@@ -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));
+}
OpenPOWER on IntegriCloud