Module Name: src
Committed By: maxv
Date: Fri Feb 9 08:03:33 UTC 2018
Modified Files:
src/sys/netinet: ip_mroute.c
Log Message:
Style (realign everything correctly), and fix a typo.
To generate a diff of this commit:
cvs rdiff -u -r1.153 -r1.154 src/sys/netinet/ip_mroute.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/netinet/ip_mroute.c
diff -u src/sys/netinet/ip_mroute.c:1.153 src/sys/netinet/ip_mroute.c:1.154
--- src/sys/netinet/ip_mroute.c:1.153 Wed Feb 7 13:22:41 2018
+++ src/sys/netinet/ip_mroute.c Fri Feb 9 08:03:33 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: ip_mroute.c,v 1.153 2018/02/07 13:22:41 maxv Exp $ */
+/* $NetBSD: ip_mroute.c,v 1.154 2018/02/09 08:03:33 maxv Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -93,7 +93,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.153 2018/02/07 13:22:41 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.154 2018/02/09 08:03:33 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -2559,88 +2559,88 @@ unschedule_bw_meter(struct bw_meter *x)
static void
bw_meter_process(void)
{
- int s;
- static uint32_t last_tv_sec; /* last time we processed this */
+ int s;
+ static uint32_t last_tv_sec; /* last time we processed this */
+
+ uint32_t loops;
+ int i;
+ struct timeval now, process_endtime;
+
+ microtime(&now);
+ if (last_tv_sec == now.tv_sec)
+ return; /* nothing to do */
+
+ loops = now.tv_sec - last_tv_sec;
+ last_tv_sec = now.tv_sec;
+ if (loops > BW_METER_BUCKETS)
+ loops = BW_METER_BUCKETS;
+
+ s = splsoftnet();
+ /*
+ * Process all bins of bw_meter entries from the one after the last
+ * processed to the current one. On entry, i points to the last bucket
+ * visited, so we need to increment i at the beginning of the loop.
+ */
+ for (i = (now.tv_sec - loops) % BW_METER_BUCKETS; loops > 0; loops--) {
+ struct bw_meter *x, *tmp_list;
+
+ if (++i >= BW_METER_BUCKETS)
+ i = 0;
+
+ /* Disconnect the list of bw_meter entries from the bin */
+ tmp_list = bw_meter_timers[i];
+ bw_meter_timers[i] = NULL;
+
+ /* Process the list of bw_meter entries */
+ while (tmp_list != NULL) {
+ x = tmp_list;
+ tmp_list = tmp_list->bm_time_next;
+
+ /* Test if the time interval is over */
+ process_endtime = x->bm_start_time;
+ BW_TIMEVALADD(&process_endtime, &x->bm_threshold.b_time);
+ if (BW_TIMEVALCMP(&process_endtime, &now, >)) {
+ /* Not yet: reschedule, but don't reset */
+ int time_hash;
+
+ BW_METER_TIMEHASH(x, time_hash);
+ if (time_hash == i && process_endtime.tv_sec == now.tv_sec) {
+ /*
+ * XXX: somehow the bin processing is a bit ahead of time.
+ * Put the entry in the next bin.
+ */
+ if (++time_hash >= BW_METER_BUCKETS)
+ time_hash = 0;
+ }
+ x->bm_time_next = bw_meter_timers[time_hash];
+ bw_meter_timers[time_hash] = x;
+ x->bm_time_hash = time_hash;
+
+ continue;
+ }
- uint32_t loops;
- int i;
- struct timeval now, process_endtime;
-
- microtime(&now);
- if (last_tv_sec == now.tv_sec)
- return; /* nothing to do */
-
- loops = now.tv_sec - last_tv_sec;
- last_tv_sec = now.tv_sec;
- if (loops > BW_METER_BUCKETS)
- loops = BW_METER_BUCKETS;
-
- s = splsoftnet();
- /*
- * Process all bins of bw_meter entries from the one after the last
- * processed to the current one. On entry, i points to the last bucket
- * visited, so we need to increment i at the beginning of the loop.
- */
- for (i = (now.tv_sec - loops) % BW_METER_BUCKETS; loops > 0; loops--) {
- struct bw_meter *x, *tmp_list;
-
- if (++i >= BW_METER_BUCKETS)
- i = 0;
-
- /* Disconnect the list of bw_meter entries from the bin */
- tmp_list = bw_meter_timers[i];
- bw_meter_timers[i] = NULL;
-
- /* Process the list of bw_meter entries */
- while (tmp_list != NULL) {
- x = tmp_list;
- tmp_list = tmp_list->bm_time_next;
-
- /* Test if the time interval is over */
- process_endtime = x->bm_start_time;
- BW_TIMEVALADD(&process_endtime, &x->bm_threshold.b_time);
- if (BW_TIMEVALCMP(&process_endtime, &now, >)) {
- /* Not yet: reschedule, but don't reset */
- int time_hash;
-
- BW_METER_TIMEHASH(x, time_hash);
- if (time_hash == i && process_endtime.tv_sec == now.tv_sec) {
- /*
- * XXX: somehow the bin processing is a bit ahead of time.
- * Put the entry in the next bin.
- */
- if (++time_hash >= BW_METER_BUCKETS)
- time_hash = 0;
- }
- x->bm_time_next = bw_meter_timers[time_hash];
- bw_meter_timers[time_hash] = x;
- x->bm_time_hash = time_hash;
-
- continue;
- }
-
- /*
- * Test if we should deliver an upcall
- */
- if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
- (x->bm_measured.b_packets <= x->bm_threshold.b_packets)) ||
- ((x->bm_flags & BW_METER_UNIT_BYTES) &&
- (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
- /* Prepare an upcall for delivery */
- bw_meter_prepare_upcall(x, &now);
- }
-
- /*
- * Reschedule for next processing
- */
- schedule_bw_meter(x, &now);
+ /*
+ * Test if we should deliver an upcall
+ */
+ if (((x->bm_flags & BW_METER_UNIT_PACKETS) &&
+ (x->bm_measured.b_packets <= x->bm_threshold.b_packets)) ||
+ ((x->bm_flags & BW_METER_UNIT_BYTES) &&
+ (x->bm_measured.b_bytes <= x->bm_threshold.b_bytes))) {
+ /* Prepare an upcall for delivery */
+ bw_meter_prepare_upcall(x, &now);
+ }
+
+ /*
+ * Reschedule for next processing
+ */
+ schedule_bw_meter(x, &now);
+ }
}
- }
- /* Send all upcalls that are pending delivery */
- bw_upcalls_send();
+ /* Send all upcalls that are pending delivery */
+ bw_upcalls_send();
- splx(s);
+ splx(s);
}
/*
@@ -2649,14 +2649,14 @@ bw_meter_process(void)
static void
expire_bw_upcalls_send(void *unused)
{
- int s;
+ int s;
- s = splsoftnet();
- bw_upcalls_send();
- splx(s);
+ s = splsoftnet();
+ bw_upcalls_send();
+ splx(s);
- callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
- expire_bw_upcalls_send, NULL);
+ callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
+ expire_bw_upcalls_send, NULL);
}
/*
@@ -2666,11 +2666,11 @@ expire_bw_upcalls_send(void *unused)
static void
expire_bw_meter_process(void *unused)
{
- if (mrt_api_config & MRT_MFC_BW_UPCALL)
- bw_meter_process();
+ if (mrt_api_config & MRT_MFC_BW_UPCALL)
+ bw_meter_process();
- callout_reset(&bw_meter_ch, BW_METER_PERIOD,
- expire_bw_meter_process, NULL);
+ callout_reset(&bw_meter_ch, BW_METER_PERIOD,
+ expire_bw_meter_process, NULL);
}
/*
@@ -2682,38 +2682,38 @@ expire_bw_meter_process(void *unused)
* Send the packet up to the user daemon, or eventually do kernel encapsulation
*/
static int
-pim_register_send(struct ip *ip, struct vif *vifp,
- struct mbuf *m, struct mfc *rt)
+pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
+ struct mfc *rt)
{
- struct mbuf *mb_copy, *mm;
+ struct mbuf *mb_copy, *mm;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG, "pim_register_send: \n");
+ if (mrtdebug & DEBUG_PIM)
+ log(LOG_DEBUG, "pim_register_send: \n");
- mb_copy = pim_register_prepare(ip, m);
- if (mb_copy == NULL)
- return ENOBUFS;
-
- /*
- * Send all the fragments. Note that the mbuf for each fragment
- * is freed by the sending machinery.
- */
- for (mm = mb_copy; mm; mm = mb_copy) {
- mb_copy = mm->m_nextpkt;
- mm->m_nextpkt = NULL;
- mm = m_pullup(mm, sizeof(struct ip));
- if (mm != NULL) {
- ip = mtod(mm, struct ip *);
- if ((mrt_api_config & MRT_MFC_RP) &&
- !in_nullhost(rt->mfc_rp)) {
- pim_register_send_rp(ip, vifp, mm, rt);
- } else {
- pim_register_send_upcall(ip, vifp, mm, rt);
- }
+ mb_copy = pim_register_prepare(ip, m);
+ if (mb_copy == NULL)
+ return ENOBUFS;
+
+ /*
+ * Send all the fragments. Note that the mbuf for each fragment
+ * is freed by the sending machinery.
+ */
+ for (mm = mb_copy; mm; mm = mb_copy) {
+ mb_copy = mm->m_nextpkt;
+ mm->m_nextpkt = NULL;
+ mm = m_pullup(mm, sizeof(struct ip));
+ if (mm != NULL) {
+ ip = mtod(mm, struct ip *);
+ if ((mrt_api_config & MRT_MFC_RP) &&
+ !in_nullhost(rt->mfc_rp)) {
+ pim_register_send_rp(ip, vifp, mm, rt);
+ } else {
+ pim_register_send_upcall(ip, vifp, mm, rt);
+ }
+ }
}
- }
- return 0;
+ return 0;
}
/*
@@ -2724,45 +2724,45 @@ pim_register_send(struct ip *ip, struct
static struct mbuf *
pim_register_prepare(struct ip *ip, struct mbuf *m)
{
- struct mbuf *mb_copy = NULL;
- int mtu;
+ struct mbuf *mb_copy = NULL;
+ int mtu;
+
+ /* Take care of delayed checksums */
+ if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
+ in_delayed_cksum(m);
+ m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
+ }
- /* Take care of delayed checksums */
- if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
- }
-
- /*
- * Copy the old packet & pullup its IP header into the
- * new mbuf so we can modify it.
- */
- mb_copy = m_copypacket(m, M_DONTWAIT);
- if (mb_copy == NULL)
- return NULL;
- mb_copy = m_pullup(mb_copy, ip->ip_hl << 2);
- if (mb_copy == NULL)
- return NULL;
-
- /* take care of the TTL */
- ip = mtod(mb_copy, struct ip *);
- --ip->ip_ttl;
+ /*
+ * Copy the old packet & pullup its IP header into the
+ * new mbuf so we can modify it.
+ */
+ mb_copy = m_copypacket(m, M_DONTWAIT);
+ if (mb_copy == NULL)
+ return NULL;
+ mb_copy = m_pullup(mb_copy, ip->ip_hl << 2);
+ if (mb_copy == NULL)
+ return NULL;
- /* Compute the MTU after the PIM Register encapsulation */
- mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr);
+ /* take care of the TTL */
+ ip = mtod(mb_copy, struct ip *);
+ --ip->ip_ttl;
- if (ntohs(ip->ip_len) <= mtu) {
- /* Turn the IP header into a valid one */
- ip->ip_sum = 0;
- ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
- } else {
- /* Fragment the packet */
- if (ip_fragment(mb_copy, NULL, mtu) != 0) {
- /* XXX: mb_copy was freed by ip_fragment() */
- return NULL;
+ /* Compute the MTU after the PIM Register encapsulation */
+ mtu = 0xffff - sizeof(pim_encap_iphdr) - sizeof(pim_encap_pimhdr);
+
+ if (ntohs(ip->ip_len) <= mtu) {
+ /* Turn the IP header into a valid one */
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
+ } else {
+ /* Fragment the packet */
+ if (ip_fragment(mb_copy, NULL, mtu) != 0) {
+ /* XXX: mb_copy was freed by ip_fragment() */
+ return NULL;
+ }
}
- }
- return mb_copy;
+ return mb_copy;
}
/*
@@ -2772,52 +2772,52 @@ static int
pim_register_send_upcall(struct ip *ip, struct vif *vifp,
struct mbuf *mb_copy, struct mfc *rt)
{
- struct mbuf *mb_first;
- int len = ntohs(ip->ip_len);
- struct igmpmsg *im;
- struct sockaddr_in k_igmpsrc = {
- .sin_len = sizeof(k_igmpsrc),
- .sin_family = AF_INET,
- };
-
- /*
- * Add a new mbuf with an upcall header
- */
- MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
- if (mb_first == NULL) {
- m_freem(mb_copy);
- return ENOBUFS;
- }
- mb_first->m_data += max_linkhdr;
- mb_first->m_pkthdr.len = len + sizeof(struct igmpmsg);
- mb_first->m_len = sizeof(struct igmpmsg);
- mb_first->m_next = mb_copy;
-
- /* Send message to routing daemon */
- im = mtod(mb_first, struct igmpmsg *);
- im->im_msgtype = IGMPMSG_WHOLEPKT;
- im->im_mbz = 0;
- im->im_vif = vifp - viftable;
- im->im_src = ip->ip_src;
- im->im_dst = ip->ip_dst;
+ struct mbuf *mb_first;
+ int len = ntohs(ip->ip_len);
+ struct igmpmsg *im;
+ struct sockaddr_in k_igmpsrc = {
+ .sin_len = sizeof(k_igmpsrc),
+ .sin_family = AF_INET,
+ };
- k_igmpsrc.sin_addr = ip->ip_src;
+ /*
+ * Add a new mbuf with an upcall header
+ */
+ MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
+ if (mb_first == NULL) {
+ m_freem(mb_copy);
+ return ENOBUFS;
+ }
+ mb_first->m_data += max_linkhdr;
+ mb_first->m_pkthdr.len = len + sizeof(struct igmpmsg);
+ mb_first->m_len = sizeof(struct igmpmsg);
+ mb_first->m_next = mb_copy;
+
+ /* Send message to routing daemon */
+ im = mtod(mb_first, struct igmpmsg *);
+ im->im_msgtype = IGMPMSG_WHOLEPKT;
+ im->im_mbz = 0;
+ im->im_vif = vifp - viftable;
+ im->im_src = ip->ip_src;
+ im->im_dst = ip->ip_dst;
- mrtstat.mrts_upcalls++;
+ k_igmpsrc.sin_addr = ip->ip_src;
- if (socket_send(ip_mrouter, mb_first, &k_igmpsrc) < 0) {
- if (mrtdebug & DEBUG_PIM)
- log(LOG_WARNING,
- "mcast: pim_register_send_upcall: ip_mrouter socket queue full\n");
- ++mrtstat.mrts_upq_sockfull;
- return ENOBUFS;
- }
-
- /* Keep statistics */
- pimstat.pims_snd_registers_msgs++;
- pimstat.pims_snd_registers_bytes += len;
+ mrtstat.mrts_upcalls++;
- return 0;
+ if (socket_send(ip_mrouter, mb_first, &k_igmpsrc) < 0) {
+ if (mrtdebug & DEBUG_PIM)
+ log(LOG_WARNING,
+ "mcast: pim_register_send_upcall: ip_mrouter socket queue full\n");
+ ++mrtstat.mrts_upq_sockfull;
+ return ENOBUFS;
+ }
+
+ /* Keep statistics */
+ pimstat.pims_snd_registers_msgs++;
+ pimstat.pims_snd_registers_bytes += len;
+
+ return 0;
}
/*
@@ -2825,74 +2825,74 @@ pim_register_send_upcall(struct ip *ip,
*/
static int
pim_register_send_rp(struct ip *ip, struct vif *vifp,
- struct mbuf *mb_copy, struct mfc *rt)
+ struct mbuf *mb_copy, struct mfc *rt)
{
- struct mbuf *mb_first;
- struct ip *ip_outer;
- struct pim_encap_pimhdr *pimhdr;
- int len = ntohs(ip->ip_len);
- vifi_t vifi = rt->mfc_parent;
-
- if ((vifi >= numvifs) || in_nullhost(viftable[vifi].v_lcl_addr)) {
- m_freem(mb_copy);
- return EADDRNOTAVAIL; /* The iif vif is invalid */
- }
-
- /*
- * Add a new mbuf with the encapsulating header
- */
- MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
- if (mb_first == NULL) {
- m_freem(mb_copy);
- return ENOBUFS;
- }
- mb_first->m_data += max_linkhdr;
- mb_first->m_len = sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
- mb_first->m_next = mb_copy;
-
- mb_first->m_pkthdr.len = len + mb_first->m_len;
-
- /*
- * Fill in the encapsulating IP and PIM header
- */
- ip_outer = mtod(mb_first, struct ip *);
- *ip_outer = pim_encap_iphdr;
- if (mb_first->m_pkthdr.len < IP_MINFRAGSIZE)
- ip_outer->ip_id = 0;
- else
- ip_outer->ip_id = ip_newid(NULL);
- ip_outer->ip_len = htons(len + sizeof(pim_encap_iphdr) +
- sizeof(pim_encap_pimhdr));
- ip_outer->ip_src = viftable[vifi].v_lcl_addr;
- ip_outer->ip_dst = rt->mfc_rp;
- /*
- * Copy the inner header TOS to the outer header, and take care of the
- * IP_DF bit.
- */
- ip_outer->ip_tos = ip->ip_tos;
- if (ntohs(ip->ip_off) & IP_DF)
- ip_outer->ip_off |= htons(IP_DF);
- pimhdr = (struct pim_encap_pimhdr *)((char *)ip_outer
- + sizeof(pim_encap_iphdr));
- *pimhdr = pim_encap_pimhdr;
- /* If the iif crosses a border, set the Border-bit */
- if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config)
- pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
-
- mb_first->m_data += sizeof(pim_encap_iphdr);
- pimhdr->pim.pim_cksum = in_cksum(mb_first, sizeof(pim_encap_pimhdr));
- mb_first->m_data -= sizeof(pim_encap_iphdr);
-
- if (vifp->v_rate_limit == 0)
- tbf_send_packet(vifp, mb_first);
- else
- tbf_control(vifp, mb_first, ip, ntohs(ip_outer->ip_len));
-
- /* Keep statistics */
- pimstat.pims_snd_registers_msgs++;
- pimstat.pims_snd_registers_bytes += len;
+ struct mbuf *mb_first;
+ struct ip *ip_outer;
+ struct pim_encap_pimhdr *pimhdr;
+ int len = ntohs(ip->ip_len);
+ vifi_t vifi = rt->mfc_parent;
+
+ if ((vifi >= numvifs) || in_nullhost(viftable[vifi].v_lcl_addr)) {
+ m_freem(mb_copy);
+ return EADDRNOTAVAIL; /* The iif vif is invalid */
+ }
- return 0;
+ /*
+ * Add a new mbuf with the encapsulating header
+ */
+ MGETHDR(mb_first, M_DONTWAIT, MT_HEADER);
+ if (mb_first == NULL) {
+ m_freem(mb_copy);
+ return ENOBUFS;
+ }
+ mb_first->m_data += max_linkhdr;
+ mb_first->m_len = sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr);
+ mb_first->m_next = mb_copy;
+
+ mb_first->m_pkthdr.len = len + mb_first->m_len;
+
+ /*
+ * Fill in the encapsulating IP and PIM header
+ */
+ ip_outer = mtod(mb_first, struct ip *);
+ *ip_outer = pim_encap_iphdr;
+ if (mb_first->m_pkthdr.len < IP_MINFRAGSIZE)
+ ip_outer->ip_id = 0;
+ else
+ ip_outer->ip_id = ip_newid(NULL);
+ ip_outer->ip_len = htons(len + sizeof(pim_encap_iphdr) +
+ sizeof(pim_encap_pimhdr));
+ ip_outer->ip_src = viftable[vifi].v_lcl_addr;
+ ip_outer->ip_dst = rt->mfc_rp;
+ /*
+ * Copy the inner header TOS to the outer header, and take care of the
+ * IP_DF bit.
+ */
+ ip_outer->ip_tos = ip->ip_tos;
+ if (ntohs(ip->ip_off) & IP_DF)
+ ip_outer->ip_off |= htons(IP_DF);
+ pimhdr = (struct pim_encap_pimhdr *)((char *)ip_outer
+ + sizeof(pim_encap_iphdr));
+ *pimhdr = pim_encap_pimhdr;
+ /* If the iif crosses a border, set the Border-bit */
+ if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config)
+ pimhdr->flags |= htonl(PIM_BORDER_REGISTER);
+
+ mb_first->m_data += sizeof(pim_encap_iphdr);
+ pimhdr->pim.pim_cksum = in_cksum(mb_first, sizeof(pim_encap_pimhdr));
+ mb_first->m_data -= sizeof(pim_encap_iphdr);
+
+ if (vifp->v_rate_limit == 0)
+ tbf_send_packet(vifp, mb_first);
+ else
+ tbf_control(vifp, mb_first, ip, ntohs(ip_outer->ip_len));
+
+ /* Keep statistics */
+ pimstat.pims_snd_registers_msgs++;
+ pimstat.pims_snd_registers_bytes += len;
+
+ return 0;
}
/*
@@ -2906,246 +2906,246 @@ pim_register_send_rp(struct ip *ip, stru
void
pim_input(struct mbuf *m, ...)
{
- struct ip *ip = mtod(m, struct ip *);
- struct pim *pim;
- int minlen;
- int datalen;
- int ip_tos;
- int proto;
- int iphlen;
- va_list ap;
-
- va_start(ap, m);
- iphlen = va_arg(ap, int);
- proto = va_arg(ap, int);
- va_end(ap);
-
- datalen = ntohs(ip->ip_len) - iphlen;
-
- /* Keep statistics */
- pimstat.pims_rcv_total_msgs++;
- pimstat.pims_rcv_total_bytes += datalen;
-
- /*
- * Validate lengths
- */
- if (datalen < PIM_MINLEN) {
- pimstat.pims_rcv_tooshort++;
- log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
- datalen, (u_long)ip->ip_src.s_addr);
- m_freem(m);
- return;
- }
-
- /*
- * If the packet is at least as big as a REGISTER, go agead
- * and grab the PIM REGISTER header size, to avoid another
- * possible m_pullup() later.
- *
- * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8
- * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28
- */
- minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN);
- /*
- * Get the IP and PIM headers in contiguous memory, and
- * possibly the PIM REGISTER header.
- */
- if ((m->m_flags & M_EXT || m->m_len < minlen) &&
- (m = m_pullup(m, minlen)) == NULL) {
- log(LOG_ERR, "pim_input: m_pullup failure\n");
- return;
- }
- /* m_pullup() may have given us a new mbuf so reset ip. */
- ip = mtod(m, struct ip *);
- ip_tos = ip->ip_tos;
-
- /* adjust mbuf to point to the PIM header */
- m->m_data += iphlen;
- m->m_len -= iphlen;
- pim = mtod(m, struct pim *);
-
- /*
- * Validate checksum. If PIM REGISTER, exclude the data packet.
- *
- * XXX: some older PIMv2 implementations don't make this distinction,
- * so for compatibility reason perform the checksum over part of the
- * message, and if error, then over the whole message.
- */
- if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {
- /* do nothing, checksum okay */
- } else if (in_cksum(m, datalen)) {
- pimstat.pims_rcv_badsum++;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG, "pim_input: invalid checksum\n");
- m_freem(m);
- return;
- }
+ struct ip *ip = mtod(m, struct ip *);
+ struct pim *pim;
+ int minlen;
+ int datalen;
+ int ip_tos;
+ int proto;
+ int iphlen;
+ va_list ap;
+
+ va_start(ap, m);
+ iphlen = va_arg(ap, int);
+ proto = va_arg(ap, int);
+ va_end(ap);
- /* PIM version check */
- if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
- pimstat.pims_rcv_badversion++;
- log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
- PIM_VT_V(pim->pim_vt), PIM_VERSION);
- m_freem(m);
- return;
- }
+ datalen = ntohs(ip->ip_len) - iphlen;
- /* restore mbuf back to the outer IP */
- m->m_data -= iphlen;
- m->m_len += iphlen;
+ /* Keep statistics */
+ pimstat.pims_rcv_total_msgs++;
+ pimstat.pims_rcv_total_bytes += datalen;
- if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER) {
/*
- * Since this is a REGISTER, we'll make a copy of the register
- * headers ip + pim + u_int32 + encap_ip, to be passed up to the
- * routing daemon.
+ * Validate lengths
*/
- int s;
- struct sockaddr_in dst = {
- .sin_len = sizeof(dst),
- .sin_family = AF_INET,
- };
- struct mbuf *mcp;
- struct ip *encap_ip;
- u_int32_t *reghdr;
- struct ifnet *vifp;
-
- s = splsoftnet();
- if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
- splx(s);
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG,
- "pim_input: register vif not set: %d\n", reg_vif_num);
- m_freem(m);
- return;
+ if (datalen < PIM_MINLEN) {
+ pimstat.pims_rcv_tooshort++;
+ log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
+ datalen, (u_long)ip->ip_src.s_addr);
+ m_freem(m);
+ return;
}
- /* XXX need refcnt? */
- vifp = viftable[reg_vif_num].v_ifp;
- splx(s);
/*
- * Validate length
+ * If the packet is at least as big as a REGISTER, go ahead
+ * and grab the PIM REGISTER header size, to avoid another
+ * possible m_pullup() later.
+ *
+ * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8
+ * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28
*/
- if (datalen < PIM_REG_MINLEN) {
- pimstat.pims_rcv_tooshort++;
- pimstat.pims_rcv_badregisters++;
- log(LOG_ERR,
- "pim_input: register packet size too small %d from %lx\n",
- datalen, (u_long)ip->ip_src.s_addr);
- m_freem(m);
- return;
- }
-
- reghdr = (u_int32_t *)(pim + 1);
- encap_ip = (struct ip *)(reghdr + 1);
-
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG,
- "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
- (u_long)ntohl(encap_ip->ip_src.s_addr),
- (u_long)ntohl(encap_ip->ip_dst.s_addr),
- ntohs(encap_ip->ip_len));
- }
-
- /* verify the version number of the inner packet */
- if (encap_ip->ip_v != IPVERSION) {
- pimstat.pims_rcv_badregisters++;
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
- "of the inner packet\n", encap_ip->ip_v);
- }
- m_freem(m);
- return;
- }
-
- /* verify the inner packet is destined to a mcast group */
- if (!IN_MULTICAST(encap_ip->ip_dst.s_addr)) {
- pimstat.pims_rcv_badregisters++;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG,
- "pim_input: inner packet of register is not "
- "multicast %lx\n",
- (u_long)ntohl(encap_ip->ip_dst.s_addr));
- m_freem(m);
- return;
- }
-
- /* If a NULL_REGISTER, pass it to the daemon */
- if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
- goto pim_input_to_daemon;
+ minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN);
/*
- * Copy the TOS from the outer IP header to the inner IP header.
+ * Get the IP and PIM headers in contiguous memory, and
+ * possibly the PIM REGISTER header.
*/
- if (encap_ip->ip_tos != ip_tos) {
- /* Outer TOS -> inner TOS */
- encap_ip->ip_tos = ip_tos;
- /* Recompute the inner header checksum. Sigh... */
-
- /* adjust mbuf to point to the inner IP header */
- m->m_data += (iphlen + PIM_MINLEN);
- m->m_len -= (iphlen + PIM_MINLEN);
+ if ((m->m_flags & M_EXT || m->m_len < minlen) &&
+ (m = m_pullup(m, minlen)) == NULL) {
+ log(LOG_ERR, "pim_input: m_pullup failure\n");
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ ip_tos = ip->ip_tos;
- encap_ip->ip_sum = 0;
- encap_ip->ip_sum = in_cksum(m, encap_ip->ip_hl << 2);
+ /* adjust mbuf to point to the PIM header */
+ m->m_data += iphlen;
+ m->m_len -= iphlen;
+ pim = mtod(m, struct pim *);
- /* restore mbuf to point back to the outer IP header */
- m->m_data -= (iphlen + PIM_MINLEN);
- m->m_len += (iphlen + PIM_MINLEN);
+ /*
+ * Validate checksum. If PIM REGISTER, exclude the data packet.
+ *
+ * XXX: some older PIMv2 implementations don't make this distinction,
+ * so for compatibility reason perform the checksum over part of the
+ * message, and if error, then over the whole message.
+ */
+ if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {
+ /* do nothing, checksum okay */
+ } else if (in_cksum(m, datalen)) {
+ pimstat.pims_rcv_badsum++;
+ if (mrtdebug & DEBUG_PIM)
+ log(LOG_DEBUG, "pim_input: invalid checksum\n");
+ m_freem(m);
+ return;
}
- /*
- * Decapsulate the inner IP packet and loopback to forward it
- * as a normal multicast packet. Also, make a copy of the
- * outer_iphdr + pimhdr + reghdr + encap_iphdr
- * to pass to the daemon later, so it can take the appropriate
- * actions (e.g., send back PIM_REGISTER_STOP).
- * XXX: here m->m_data points to the outer IP header.
- */
- mcp = m_copym(m, 0, iphlen + PIM_REG_MINLEN, M_DONTWAIT);
- if (mcp == NULL) {
- log(LOG_ERR,
- "pim_input: pim register: could not copy register head\n");
- m_freem(m);
- return;
+ /* PIM version check */
+ if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
+ pimstat.pims_rcv_badversion++;
+ log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
+ PIM_VT_V(pim->pim_vt), PIM_VERSION);
+ m_freem(m);
+ return;
}
- /* Keep statistics */
- /* XXX: registers_bytes include only the encap. mcast pkt */
- pimstat.pims_rcv_registers_msgs++;
- pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
+ /* restore mbuf back to the outer IP */
+ m->m_data -= iphlen;
+ m->m_len += iphlen;
- /*
- * forward the inner ip packet; point m_data at the inner ip.
- */
- m_adj(m, iphlen + PIM_MINLEN);
+ if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER) {
+ /*
+ * Since this is a REGISTER, we'll make a copy of the register
+ * headers ip + pim + u_int32 + encap_ip, to be passed up to the
+ * routing daemon.
+ */
+ int s;
+ struct sockaddr_in dst = {
+ .sin_len = sizeof(dst),
+ .sin_family = AF_INET,
+ };
+ struct mbuf *mcp;
+ struct ip *encap_ip;
+ u_int32_t *reghdr;
+ struct ifnet *vifp;
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG,
- "pim_input: forwarding decapsulated register: "
- "src %lx, dst %lx, vif %d\n",
- (u_long)ntohl(encap_ip->ip_src.s_addr),
- (u_long)ntohl(encap_ip->ip_dst.s_addr),
- reg_vif_num);
- }
- /* NB: vifp was collected above; can it change on us? */
- looutput(vifp, m, (struct sockaddr *)&dst, NULL);
+ s = splsoftnet();
+ if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
+ splx(s);
+ if (mrtdebug & DEBUG_PIM)
+ log(LOG_DEBUG,
+ "pim_input: register vif not set: %d\n", reg_vif_num);
+ m_freem(m);
+ return;
+ }
+ /* XXX need refcnt? */
+ vifp = viftable[reg_vif_num].v_ifp;
+ splx(s);
+
+ /*
+ * Validate length
+ */
+ if (datalen < PIM_REG_MINLEN) {
+ pimstat.pims_rcv_tooshort++;
+ pimstat.pims_rcv_badregisters++;
+ log(LOG_ERR,
+ "pim_input: register packet size too small %d from %lx\n",
+ datalen, (u_long)ip->ip_src.s_addr);
+ m_freem(m);
+ return;
+ }
+
+ reghdr = (u_int32_t *)(pim + 1);
+ encap_ip = (struct ip *)(reghdr + 1);
+
+ if (mrtdebug & DEBUG_PIM) {
+ log(LOG_DEBUG,
+ "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
+ (u_long)ntohl(encap_ip->ip_src.s_addr),
+ (u_long)ntohl(encap_ip->ip_dst.s_addr),
+ ntohs(encap_ip->ip_len));
+ }
+
+ /* verify the version number of the inner packet */
+ if (encap_ip->ip_v != IPVERSION) {
+ pimstat.pims_rcv_badregisters++;
+ if (mrtdebug & DEBUG_PIM) {
+ log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
+ "of the inner packet\n", encap_ip->ip_v);
+ }
+ m_freem(m);
+ return;
+ }
+
+ /* verify the inner packet is destined to a mcast group */
+ if (!IN_MULTICAST(encap_ip->ip_dst.s_addr)) {
+ pimstat.pims_rcv_badregisters++;
+ if (mrtdebug & DEBUG_PIM)
+ log(LOG_DEBUG,
+ "pim_input: inner packet of register is not "
+ "multicast %lx\n",
+ (u_long)ntohl(encap_ip->ip_dst.s_addr));
+ m_freem(m);
+ return;
+ }
- /* prepare the register head to send to the mrouting daemon */
- m = mcp;
- }
+ /* If a NULL_REGISTER, pass it to the daemon */
+ if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
+ goto pim_input_to_daemon;
+
+ /*
+ * Copy the TOS from the outer IP header to the inner IP header.
+ */
+ if (encap_ip->ip_tos != ip_tos) {
+ /* Outer TOS -> inner TOS */
+ encap_ip->ip_tos = ip_tos;
+ /* Recompute the inner header checksum. Sigh... */
+
+ /* adjust mbuf to point to the inner IP header */
+ m->m_data += (iphlen + PIM_MINLEN);
+ m->m_len -= (iphlen + PIM_MINLEN);
+
+ encap_ip->ip_sum = 0;
+ encap_ip->ip_sum = in_cksum(m, encap_ip->ip_hl << 2);
+
+ /* restore mbuf to point back to the outer IP header */
+ m->m_data -= (iphlen + PIM_MINLEN);
+ m->m_len += (iphlen + PIM_MINLEN);
+ }
+
+ /*
+ * Decapsulate the inner IP packet and loopback to forward it
+ * as a normal multicast packet. Also, make a copy of the
+ * outer_iphdr + pimhdr + reghdr + encap_iphdr
+ * to pass to the daemon later, so it can take the appropriate
+ * actions (e.g., send back PIM_REGISTER_STOP).
+ * XXX: here m->m_data points to the outer IP header.
+ */
+ mcp = m_copym(m, 0, iphlen + PIM_REG_MINLEN, M_DONTWAIT);
+ if (mcp == NULL) {
+ log(LOG_ERR,
+ "pim_input: pim register: could not copy register head\n");
+ m_freem(m);
+ return;
+ }
+
+ /* Keep statistics */
+ /* XXX: registers_bytes include only the encap. mcast pkt */
+ pimstat.pims_rcv_registers_msgs++;
+ pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
+
+ /*
+ * forward the inner ip packet; point m_data at the inner ip.
+ */
+ m_adj(m, iphlen + PIM_MINLEN);
+
+ if (mrtdebug & DEBUG_PIM) {
+ log(LOG_DEBUG,
+ "pim_input: forwarding decapsulated register: "
+ "src %lx, dst %lx, vif %d\n",
+ (u_long)ntohl(encap_ip->ip_src.s_addr),
+ (u_long)ntohl(encap_ip->ip_dst.s_addr),
+ reg_vif_num);
+ }
+ /* NB: vifp was collected above; can it change on us? */
+ looutput(vifp, m, (struct sockaddr *)&dst, NULL);
+
+ /* prepare the register head to send to the mrouting daemon */
+ m = mcp;
+ }
pim_input_to_daemon:
- /*
- * Pass the PIM message up to the daemon; if it is a Register message,
- * pass the 'head' only up to the daemon. This includes the
- * outer IP header, PIM header, PIM-Register header and the
- * inner IP header.
- * XXX: the outer IP header pkt size of a Register is not adjust to
- * reflect the fact that the inner multicast data is truncated.
- */
- rip_input(m, iphlen, proto);
+ /*
+ * Pass the PIM message up to the daemon; if it is a Register message,
+ * pass the 'head' only up to the daemon. This includes the
+ * outer IP header, PIM header, PIM-Register header and the
+ * inner IP header.
+ * XXX: the outer IP header pkt size of a Register is not adjust to
+ * reflect the fact that the inner multicast data is truncated.
+ */
+ rip_input(m, iphlen, proto);
- return;
+ return;
}
#endif /* PIM */