]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_mroute.c
pimd: Remove some extraneous hexdump's
[mirror_frr.git] / pimd / pim_mroute.c
CommitLineData
12e41d03
DL
1/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
18 MA 02110-1301 USA
19
20 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include <zebra.h>
24#include "log.h"
25#include "privs.h"
744d91b3 26#include "if.h"
065bee4b 27#include "prefix.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_mroute.h"
37653d4f 31#include "pim_oil.h"
12e41d03
DL
32#include "pim_str.h"
33#include "pim_time.h"
34#include "pim_iface.h"
35#include "pim_macro.h"
c8ae3ce8 36#include "pim_rp.h"
59471fb8 37#include "pim_oil.h"
998af219 38#include "pim_register.h"
12e41d03
DL
39
40/* GLOBAL VARS */
41extern struct zebra_privs_t pimd_privs;
42
43static void mroute_read_on(void);
44
45static int pim_mroute_set(int fd, int enable)
46{
47 int err;
48 int opt = enable ? MRT_INIT : MRT_DONE;
49 socklen_t opt_len = sizeof(opt);
50
51 err = setsockopt(fd, IPPROTO_IP, opt, &opt, opt_len);
52 if (err) {
53 int e = errno;
54 zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
55 __FILE__, __PRETTY_FUNCTION__,
56 fd, enable ? "MRT_INIT" : "MRT_DONE", opt, e, safe_strerror(e));
57 errno = e;
58 return -1;
59 }
60
61#if 0
62 zlog_info("%s %s: setsockopt(fd=%d,IPPROTO_IP,MRT_INIT,opt=%d): ok",
63 __FILE__, __PRETTY_FUNCTION__,
64 fd, opt);
65#endif
66
67 return 0;
68}
69
065bee4b
DS
70static int
71pim_mroute_connected_to_source (struct interface *ifp, struct in_addr src)
72{
73 struct listnode *cnode;
74 struct connected *c;
75 struct prefix p;
76
77 p.family = AF_INET;
78 p.u.prefix4 = src;
79 p.prefixlen = IPV4_MAX_BITLEN;
80
81 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
82 {
83 if ((c->address->family == AF_INET) &&
84 prefix_match (CONNECTED_PREFIX (c), &p))
85 {
86 return 1;
87 }
88 }
89
90 return 0;
91}
92
e355e30f
DS
93static const char *igmpmsgtype2str[IGMPMSG_WHOLEPKT + 1] = {
94 "<unknown_upcall?>",
95 "NOCACHE",
96 "WRONGVIF",
97 "WHOLEPKT", };
98
99static int
100pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg,
101 const char *src_str, const char *grp_str)
12e41d03 102{
04b40f02 103 struct pim_interface *pim_ifp = ifp->info;
59471fb8 104 struct pim_upstream *up;
065bee4b 105 struct pim_rpf *rpg;
04b40f02 106
c8ae3ce8 107 rpg = RP(msg->im_dst);
04b40f02
DS
108 /*
109 * If the incoming interface is unknown OR
110 * the Interface type is SSM we don't need to
111 * do anything here
112 */
ed66602c 113 if ((rpg->rpf_addr.s_addr == INADDR_NONE) ||
04b40f02 114 (!pim_ifp) ||
b45fd505 115 (!(PIM_I_am_DR(pim_ifp))) ||
04b40f02
DS
116 (pim_ifp->itype == PIM_INTERFACE_SSM))
117 return 0;
118
065bee4b
DS
119 /*
120 * If we've received a multicast packet that isn't connected to
121 * us
122 */
123 if (!pim_mroute_connected_to_source (ifp, msg->im_src))
124 {
125 if (PIM_DEBUG_PIM_TRACE)
126 zlog_debug ("%s: Received incoming packet that does originate on our seg",
127 __PRETTY_FUNCTION__);
128 return 0;
129 }
130
04b40f02
DS
131 if (PIM_DEBUG_PIM_TRACE) {
132 zlog_debug("%s: Adding a Route for %s from %s for WHOLEPKT consumption",
133 __PRETTY_FUNCTION__, grp_str, src_str);
134 }
8813406f 135
651d0f71 136 up = pim_upstream_add(msg->im_src, msg->im_dst, ifp);
59471fb8
DS
137 if (!up) {
138 if (PIM_DEBUG_PIM_TRACE) {
139 zlog_debug("%s: Failure to add upstream information for (%s,%s)",
140 __PRETTY_FUNCTION__,
141 src_str, grp_str);
142 }
143 return 0;
144 }
145
3667e8a0
DS
146 pim_upstream_keep_alive_timer_start (up, PIM_KEEPALIVE_PERIOD);
147
59471fb8
DS
148 up->channel_oil = pim_channel_oil_add(msg->im_dst,
149 msg->im_src,
150 pim_ifp->mroute_vif_index);
151 if (!up->channel_oil) {
152 if (PIM_DEBUG_PIM_TRACE) {
153 zlog_debug("%s: Failure to add channel oil for (%s,%s)",
154 __PRETTY_FUNCTION__,
155 src_str, grp_str);
156 }
157 return 0;
158 }
159
160 pim_channel_add_oif(up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_SOURCE);
161
e355e30f
DS
162 return 0;
163}
12e41d03 164
e355e30f 165static int
c8ae3ce8 166pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf,
e355e30f
DS
167 const char *src_str, const char *grp_str)
168{
59471fb8 169 struct pim_interface *pim_ifp;
c8ae3ce8 170 struct in_addr group;
59471fb8 171 struct in_addr src;
ed66602c 172 struct pim_rpf *rpg;
c8ae3ce8 173 const struct ip *ip_hdr;
59471fb8 174 struct pim_upstream *up;
04b40f02 175
c8ae3ce8
DS
176 ip_hdr = (const struct ip *)buf;
177
59471fb8 178 src = ip_hdr->ip_src;
c8ae3ce8
DS
179 group = ip_hdr->ip_dst;
180
59471fb8
DS
181 up = pim_upstream_find(src, group);
182 if (!up) {
183 if (PIM_DEBUG_PIM_TRACE) {
184 zlog_debug("%s: Unable to find upstream channel WHOLEPKT(%s,%s)",
185 __PRETTY_FUNCTION__, src_str, grp_str);
186 }
187 return 0;
188 }
189
998af219
DS
190 pim_ifp = up->rpf.source_nexthop.interface->info;
191
c8ae3ce8
DS
192 rpg = RP(group);
193
ed66602c 194 if ((rpg->rpf_addr.s_addr == INADDR_NONE) ||
c8ae3ce8 195 (!pim_ifp) ||
b45fd505 196 (!(PIM_I_am_DR(pim_ifp))) ||
c8ae3ce8 197 (pim_ifp->itype == PIM_INTERFACE_SSM)) {
998af219
DS
198 if (PIM_DEBUG_PIM_TRACE) {
199 zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__);
200 }
c8ae3ce8 201 return 0;
04b40f02 202 }
84366c7e 203
998af219 204 pim_register_send((const struct ip *)(buf + sizeof(struct ip)), rpg);
e355e30f
DS
205 return 0;
206}
12e41d03 207
e355e30f
DS
208static int
209pim_mroute_msg_wrongvif (int fd, struct interface *ifp, const struct igmpmsg *msg,
210 const char *src_str, const char *grp_str)
211{
212 struct pim_ifchannel *ch;
213 struct pim_interface *pim_ifp;
12e41d03 214
e355e30f
DS
215 /*
216 Send Assert(S,G) on iif as response to WRONGVIF kernel upcall.
12e41d03 217
e355e30f
DS
218 RFC 4601 4.8.2. PIM-SSM-Only Routers
219
220 iif is the incoming interface of the packet.
221 if (iif is in inherited_olist(S,G)) {
222 send Assert(S,G) on iif
223 }
224 */
12e41d03 225
e355e30f 226 if (!ifp) {
12e41d03 227 if (PIM_DEBUG_PIM_TRACE) {
e355e30f 228 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find input interface for input_vif_index=%d",
12e41d03 229 __PRETTY_FUNCTION__,
e355e30f 230 src_str, grp_str, msg->im_vif);
12e41d03 231 }
e355e30f
DS
232 return -1;
233 }
12e41d03 234
e355e30f
DS
235 pim_ifp = ifp->info;
236 if (!pim_ifp) {
237 if (PIM_DEBUG_PIM_TRACE) {
238 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) multicast not enabled on interface %s",
239 __PRETTY_FUNCTION__,
240 src_str, grp_str, ifp->name);
12e41d03 241 }
e355e30f
DS
242 return -2;
243 }
12e41d03 244
e355e30f
DS
245 ch = pim_ifchannel_find(ifp, msg->im_src, msg->im_dst);
246 if (!ch) {
247 if (PIM_DEBUG_PIM_TRACE) {
248 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) could not find channel on interface %s",
249 __PRETTY_FUNCTION__,
250 src_str, grp_str, ifp->name);
12e41d03 251 }
e355e30f
DS
252 return -3;
253 }
12e41d03 254
e355e30f
DS
255 /*
256 RFC 4601: 4.6.1. (S,G) Assert Message State Machine
257
258 Transitions from NoInfo State
259
260 An (S,G) data packet arrives on interface I, AND
261 CouldAssert(S,G,I)==TRUE An (S,G) data packet arrived on an
262 downstream interface that is in our (S,G) outgoing interface
263 list. We optimistically assume that we will be the assert
264 winner for this (S,G), and so we transition to the "I am Assert
265 Winner" state and perform Actions A1 (below), which will
266 initiate the assert negotiation for (S,G).
267 */
12e41d03 268
e355e30f
DS
269 if (ch->ifassert_state != PIM_IFASSERT_NOINFO) {
270 if (PIM_DEBUG_PIM_TRACE) {
271 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) channel is not on Assert NoInfo state for interface %s",
272 __PRETTY_FUNCTION__,
273 src_str, grp_str, ifp->name);
12e41d03 274 }
e355e30f
DS
275 return -4;
276 }
12e41d03 277
e355e30f
DS
278 if (!PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) {
279 if (PIM_DEBUG_PIM_TRACE) {
280 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) interface %s is not downstream for channel",
281 __PRETTY_FUNCTION__,
282 src_str, grp_str, ifp->name);
12e41d03 283 }
e355e30f
DS
284 return -5;
285 }
12e41d03 286
e355e30f
DS
287 if (assert_action_a1(ch)) {
288 if (PIM_DEBUG_PIM_TRACE) {
289 zlog_debug("%s: WRONGVIF (S,G)=(%s,%s) assert_action_a1 failure on interface %s",
290 __PRETTY_FUNCTION__,
291 src_str, grp_str, ifp->name);
12e41d03 292 }
e355e30f
DS
293 return -6;
294 }
295
296 return 0;
297}
298
299int pim_mroute_msg(int fd, const char *buf, int buf_size)
300{
301 struct interface *ifp;
302 const struct ip *ip_hdr;
303 const struct igmpmsg *msg;
304 char src_str[100] = "<src?>";
305 char grp_str[100] = "<grp?>";
12e41d03 306
e355e30f
DS
307 ip_hdr = (const struct ip *) buf;
308
309 /* kernel upcall must have protocol=0 */
310 if (ip_hdr->ip_p) {
311 /* this is not a kernel upcall */
312 if (PIM_DEBUG_PIM_TRACE) {
e5d33c83
DS
313 pim_inet4_dump("<src?>", ip_hdr->ip_src, src_str, sizeof(src_str));
314 pim_inet4_dump("<grp?>", ip_hdr->ip_dst, grp_str, sizeof(grp_str));
315 zlog_debug("%s: not a kernel upcall proto=%d src: %s dst: %s msg_size=%d",
316 __PRETTY_FUNCTION__, ip_hdr->ip_p, src_str, grp_str, buf_size);
e355e30f 317 }
12e41d03 318 return 0;
e355e30f
DS
319 }
320
321 msg = (const struct igmpmsg *) buf;
322
323 ifp = pim_if_find_by_vif_index(msg->im_vif);
324
325 if (PIM_DEBUG_PIM_TRACE) {
326 pim_inet4_dump("<src?>", msg->im_src, src_str, sizeof(src_str));
327 pim_inet4_dump("<grp?>", msg->im_dst, grp_str, sizeof(grp_str));
328 zlog_warn("%s: kernel upcall %s type=%d ip_p=%d from fd=%d for (S,G)=(%s,%s) on %s vifi=%d",
329 __PRETTY_FUNCTION__,
330 igmpmsgtype2str[msg->im_msgtype],
331 msg->im_msgtype,
332 ip_hdr->ip_p,
333 fd,
334 src_str,
335 grp_str,
336 ifp ? ifp->name : "<ifname?>",
337 msg->im_vif);
338 }
339
340 switch (msg->im_msgtype) {
341 case IGMPMSG_WRONGVIF:
342 return pim_mroute_msg_wrongvif(fd, ifp, msg, src_str, grp_str);
343 break;
344 case IGMPMSG_NOCACHE:
345 return pim_mroute_msg_nocache(fd, ifp, msg, src_str, grp_str);
346 break;
347 case IGMPMSG_WHOLEPKT:
9f6d6b12 348 return pim_mroute_msg_wholepkt(fd, ifp, (const char *)msg, src_str, grp_str);
e355e30f
DS
349 break;
350 default:
351 break;
352 }
12e41d03
DL
353
354 return 0;
355}
356
357static int mroute_read_msg(int fd)
358{
359 const int msg_min_size = MAX(sizeof(struct ip), sizeof(struct igmpmsg));
360 char buf[1000];
361 int rd;
362
363 if (((int) sizeof(buf)) < msg_min_size) {
364 zlog_err("%s: fd=%d: buf size=%zu lower than msg_min=%d",
365 __PRETTY_FUNCTION__, fd, sizeof(buf), msg_min_size);
366 return -1;
367 }
368
369 rd = read(fd, buf, sizeof(buf));
370 if (rd < 0) {
371 zlog_warn("%s: failure reading fd=%d: errno=%d: %s",
372 __PRETTY_FUNCTION__, fd, errno, safe_strerror(errno));
373 return -2;
374 }
375
376 if (rd < msg_min_size) {
377 zlog_warn("%s: short message reading fd=%d: read=%d msg_min=%d",
378 __PRETTY_FUNCTION__, fd, rd, msg_min_size);
379 return -3;
380 }
381
382 return pim_mroute_msg(fd, buf, rd);
383}
384
385static int mroute_read(struct thread *t)
386{
387 int fd;
388 int result;
389
390 zassert(t);
391 zassert(!THREAD_ARG(t));
392
393 fd = THREAD_FD(t);
394 zassert(fd == qpim_mroute_socket_fd);
395
396 result = mroute_read_msg(fd);
397
398 /* Keep reading */
399 qpim_mroute_socket_reader = 0;
400 mroute_read_on();
401
402 return result;
403}
404
405static void mroute_read_on()
406{
407 zassert(!qpim_mroute_socket_reader);
408 zassert(PIM_MROUTE_IS_ENABLED);
409
410 THREAD_READ_ON(master, qpim_mroute_socket_reader,
411 mroute_read, 0, qpim_mroute_socket_fd);
412}
413
414static void mroute_read_off()
415{
416 THREAD_OFF(qpim_mroute_socket_reader);
417}
418
419int pim_mroute_socket_enable()
420{
421 int fd;
422
423 if (PIM_MROUTE_IS_ENABLED)
424 return -1;
425
426 if ( pimd_privs.change (ZPRIVS_RAISE) )
427 zlog_err ("pim_mroute_socket_enable: could not raise privs, %s",
428 safe_strerror (errno) );
429
430 fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
431
432 if ( pimd_privs.change (ZPRIVS_LOWER) )
433 zlog_err ("pim_mroute_socket_enable: could not lower privs, %s",
434 safe_strerror (errno) );
435
436 if (fd < 0) {
437 zlog_warn("Could not create mroute socket: errno=%d: %s",
438 errno, safe_strerror(errno));
439 return -2;
440 }
441
442 if (pim_mroute_set(fd, 1)) {
443 zlog_warn("Could not enable mroute on socket fd=%d: errno=%d: %s",
444 fd, errno, safe_strerror(errno));
445 close(fd);
446 return -3;
447 }
448
449 qpim_mroute_socket_fd = fd;
b45cefcb 450
12e41d03
DL
451 qpim_mroute_socket_creation = pim_time_monotonic_sec();
452 mroute_read_on();
453
454 zassert(PIM_MROUTE_IS_ENABLED);
455
456 return 0;
457}
458
459int pim_mroute_socket_disable()
460{
461 if (PIM_MROUTE_IS_DISABLED)
462 return -1;
463
464 if (pim_mroute_set(qpim_mroute_socket_fd, 0)) {
465 zlog_warn("Could not disable mroute on socket fd=%d: errno=%d: %s",
466 qpim_mroute_socket_fd, errno, safe_strerror(errno));
467 return -2;
468 }
469
470 if (close(qpim_mroute_socket_fd)) {
471 zlog_warn("Failure closing mroute socket: fd=%d errno=%d: %s",
472 qpim_mroute_socket_fd, errno, safe_strerror(errno));
473 return -3;
474 }
475
476 mroute_read_off();
477 qpim_mroute_socket_fd = -1;
478
479 zassert(PIM_MROUTE_IS_DISABLED);
480
481 return 0;
482}
483
484/*
485 For each network interface (e.g., physical or a virtual tunnel) that
486 would be used for multicast forwarding, a corresponding multicast
487 interface must be added to the kernel.
488 */
744d91b3 489int pim_mroute_add_vif(struct interface *ifp, struct in_addr ifaddr, unsigned char flags)
12e41d03 490{
744d91b3 491 struct pim_interface *pim_ifp = ifp->info;
12e41d03
DL
492 struct vifctl vc;
493 int err;
494
495 if (PIM_MROUTE_IS_DISABLED) {
496 zlog_warn("%s: global multicast is disabled",
497 __PRETTY_FUNCTION__);
498 return -1;
499 }
500
501 memset(&vc, 0, sizeof(vc));
744d91b3
DS
502 vc.vifc_vifi = pim_ifp->mroute_vif_index;
503 vc.vifc_lcl_ifindex = ifp->ifindex;
b45cefcb 504 vc.vifc_flags = flags;
12e41d03
DL
505 vc.vifc_threshold = PIM_MROUTE_MIN_TTL;
506 vc.vifc_rate_limit = 0;
12e41d03
DL
507
508#ifdef PIM_DVMRP_TUNNEL
509 if (vc.vifc_flags & VIFF_TUNNEL) {
510 memcpy(&vc.vifc_rmt_addr, &vif_remote_addr, sizeof(vc.vifc_rmt_addr));
511 }
512#endif
513
b45cefcb 514 err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_VIF, (void*) &vc, sizeof(vc));
12e41d03
DL
515 if (err) {
516 char ifaddr_str[100];
517 int e = errno;
518
519 pim_inet4_dump("<ifaddr?>", ifaddr, ifaddr_str, sizeof(ifaddr_str));
520
59471fb8 521 zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_VIF,vif_index=%d,ifaddr=%s,flag=%d): errno=%d: %s",
12e41d03 522 __FILE__, __PRETTY_FUNCTION__,
744d91b3 523 qpim_mroute_socket_fd, ifp->ifindex, ifaddr_str, flags,
12e41d03
DL
524 e, safe_strerror(e));
525 errno = e;
526 return -2;
527 }
528
529 return 0;
530}
531
532int pim_mroute_del_vif(int vif_index)
533{
534 struct vifctl vc;
535 int err;
536
537 if (PIM_MROUTE_IS_DISABLED) {
538 zlog_warn("%s: global multicast is disabled",
539 __PRETTY_FUNCTION__);
540 return -1;
541 }
542
543 memset(&vc, 0, sizeof(vc));
544 vc.vifc_vifi = vif_index;
545
546 err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_VIF, (void*) &vc, sizeof(vc));
547 if (err) {
548 int e = errno;
549 zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_VIF,vif_index=%d): errno=%d: %s",
550 __FILE__, __PRETTY_FUNCTION__,
551 qpim_mroute_socket_fd, vif_index,
552 e, safe_strerror(e));
553 errno = e;
554 return -2;
555 }
556
557 return 0;
558}
559
c171d6d8 560int pim_mroute_add(struct channel_oil *c_oil)
12e41d03
DL
561{
562 int err;
2ca35b3d 563 int orig = 0;
12e41d03
DL
564
565 qpim_mroute_add_last = pim_time_monotonic_sec();
566 ++qpim_mroute_add_events;
567
568 if (PIM_MROUTE_IS_DISABLED) {
569 zlog_warn("%s: global multicast is disabled",
570 __PRETTY_FUNCTION__);
571 return -1;
572 }
573
d3aded99
DS
574 /* The linux kernel *expects* the incoming
575 * vif to be part of the outgoing list
576 * in the case of a (*,G).
577 */
c171d6d8 578 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
d3aded99 579 {
c171d6d8
DS
580 orig = c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent];
581 c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = 1;
d3aded99
DS
582 }
583
12e41d03 584 err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_ADD_MFC,
c171d6d8 585 &c_oil->oil, sizeof(c_oil->oil));
d3aded99 586
c171d6d8
DS
587 if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
588 c_oil->oil.mfcc_ttls[c_oil->oil.mfcc_parent] = orig;
d3aded99 589
12e41d03
DL
590 if (err) {
591 int e = errno;
592 zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_ADD_MFC): errno=%d: %s",
593 __FILE__, __PRETTY_FUNCTION__,
594 qpim_mroute_socket_fd,
595 e, safe_strerror(e));
596 errno = e;
597 return -2;
598 }
599
58302dc7 600 c_oil->installed = 1;
12e41d03
DL
601 return 0;
602}
603
c171d6d8 604int pim_mroute_del (struct channel_oil *c_oil)
12e41d03
DL
605{
606 int err;
607
608 qpim_mroute_del_last = pim_time_monotonic_sec();
609 ++qpim_mroute_del_events;
610
611 if (PIM_MROUTE_IS_DISABLED) {
612 zlog_warn("%s: global multicast is disabled",
613 __PRETTY_FUNCTION__);
614 return -1;
615 }
616
c171d6d8 617 err = setsockopt(qpim_mroute_socket_fd, IPPROTO_IP, MRT_DEL_MFC, &c_oil->oil, sizeof(c_oil->oil));
12e41d03
DL
618 if (err) {
619 int e = errno;
620 zlog_warn("%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,MRT_DEL_MFC): errno=%d: %s",
621 __FILE__, __PRETTY_FUNCTION__,
622 qpim_mroute_socket_fd,
623 e, safe_strerror(e));
624 errno = e;
625 return -2;
626 }
627
58302dc7
DS
628 c_oil->installed = 0;
629
12e41d03
DL
630 return 0;
631}
3667e8a0
DS
632
633void
634pim_mroute_update_counters (struct channel_oil *c_oil)
635{
636 struct sioc_sg_req sgreq;
637
638 memset (&sgreq, 0, sizeof(sgreq));
639 sgreq.src = c_oil->oil.mfcc_origin;
640 sgreq.grp = c_oil->oil.mfcc_mcastgrp;
641
642 c_oil->cc.oldpktcnt = c_oil->cc.pktcnt;
643 c_oil->cc.oldbytecnt = c_oil->cc.bytecnt;
644 c_oil->cc.oldwrong_if = c_oil->cc.wrong_if;
645
646 if (ioctl (qpim_mroute_socket_fd, SIOCGETSGCNT, &sgreq))
647 {
648 char group_str[100];
649 char source_str[100];
650
651 pim_inet4_dump("<group?>", c_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str));
652 pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, source_str, sizeof(source_str));
653
654 zlog_warn ("ioctl(SIOCGETSGCNT=%lu) failure for (S,G)=(%s,%s): errno=%d: %s",
655 (unsigned long)SIOCGETSGCNT,
656 source_str,
657 group_str,
658 errno,
659 safe_strerror(errno));
660 return;
661 }
662
663 c_oil->cc.pktcnt = sgreq.pktcnt;
664 c_oil->cc.bytecnt = sgreq.bytecnt;
665 c_oil->cc.wrong_if = sgreq.wrong_if;
666
667 return;
668}