ip_mroute.c (b72bec6c) ip_mroute.c (77c03cb2)
1/* $OpenBSD: ip_mroute.c,v 1.94 2016/12/13 09:22:18 rzalamena Exp $ */
1/* $OpenBSD: ip_mroute.c,v 1.95 2016/12/19 09:22:24 rzalamena Exp $ */
2/* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */
3
4/*
5 * Copyright (c) 1989 Stephen Deering
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by

--- 87 unchanged lines hidden (view full) ---

97 if ((m) && ((m)->m_flags & M_EXT || (m)->m_len < (len))) \
98 (m) = m_pullup((m), (len)); \
99 } while (/*CONSTCOND*/ 0)
100
101/*
102 * Globals. All but ip_mrouter and ip_mrtproto could be static,
103 * except for netstat or debugging purposes.
104 */
2/* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */
3
4/*
5 * Copyright (c) 1989 Stephen Deering
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by

--- 87 unchanged lines hidden (view full) ---

97 if ((m) && ((m)->m_flags & M_EXT || (m)->m_len < (len))) \
98 (m) = m_pullup((m), (len)); \
99 } while (/*CONSTCOND*/ 0)
100
101/*
102 * Globals. All but ip_mrouter and ip_mrtproto could be static,
103 * except for netstat or debugging purposes.
104 */
105struct socket *ip_mrouter = NULL;
105struct socket *ip_mrouter[RT_TABLEID_MAX];
106int ip_mrtproto = IGMP_DVMRP; /* for netstat only */
107
108#define NO_RTE_FOUND 0x1
109#define RTE_FOUND 0x2
110
106int ip_mrtproto = IGMP_DVMRP; /* for netstat only */
107
108#define NO_RTE_FOUND 0x1
109#define RTE_FOUND 0x2
110
111u_int32_t _mfchash(struct in_addr, struct in_addr);
111u_int32_t _mfchash(unsigned int, struct in_addr, struct in_addr);
112
112
113#define MFCHASH(a, g) _mfchash((a), (g))
114LIST_HEAD(mfchashhdr, mfc) *mfchashtbl;
115u_long mfchash;
116SIPHASH_KEY mfchashkey;
113#define MFCHASH(r, a, g) _mfchash((r), (a), (g))
114LIST_HEAD(mfchashhdr, mfc) *mfchashtbl[RT_TABLEID_MAX];
115u_long mfchash[RT_TABLEID_MAX];
116SIPHASH_KEY mfchashkey[RT_TABLEID_MAX];
117
117
118u_char nexpire[MFCTBLSIZ];
118u_char nexpire[RT_TABLEID_MAX][MFCTBLSIZ];
119struct vif viftable[MAXVIFS];
120struct mrtstat mrtstat;
121
122#define VIFI_INVALID ((vifi_t) -1)
123
124#define EXPIRE_TIMEOUT 250 /* 4x / second */
125#define UPCALL_EXPIRE 6 /* number of timeouts */
126struct timeout expire_upcalls_ch;
127
119struct vif viftable[MAXVIFS];
120struct mrtstat mrtstat;
121
122#define VIFI_INVALID ((vifi_t) -1)
123
124#define EXPIRE_TIMEOUT 250 /* 4x / second */
125#define UPCALL_EXPIRE 6 /* number of timeouts */
126struct timeout expire_upcalls_ch;
127
128int get_sg_cnt(struct sioc_sg_req *);
128int get_sg_cnt(unsigned int, struct sioc_sg_req *);
129int get_vif_cnt(struct sioc_vif_req *);
130int get_vif_ctl(struct vifctl *);
131int ip_mrouter_init(struct socket *, struct mbuf *);
132int get_version(struct mbuf *);
133int add_vif(struct socket *, struct mbuf *);
134int del_vif(struct mbuf *);
135void update_mfc_params(struct mfc *, struct mfcctl2 *);
136void init_mfc_params(struct mfc *, struct mfcctl2 *);
137void expire_mfc(struct mfc *);
129int get_vif_cnt(struct sioc_vif_req *);
130int get_vif_ctl(struct vifctl *);
131int ip_mrouter_init(struct socket *, struct mbuf *);
132int get_version(struct mbuf *);
133int add_vif(struct socket *, struct mbuf *);
134int del_vif(struct mbuf *);
135void update_mfc_params(struct mfc *, struct mfcctl2 *);
136void init_mfc_params(struct mfc *, struct mfcctl2 *);
137void expire_mfc(struct mfc *);
138int add_mfc(struct mbuf *);
139int del_mfc(struct mbuf *);
140int set_api_config(struct mbuf *); /* chose API capabilities */
138int add_mfc(struct socket *, struct mbuf *);
139int del_mfc(struct socket *, struct mbuf *);
140int set_api_config(struct socket *, struct mbuf *); /* chose API capabilities */
141int get_api_support(struct mbuf *);
142int get_api_config(struct mbuf *);
143int socket_send(struct socket *, struct mbuf *,
144 struct sockaddr_in *);
145void expire_upcalls(void *);
146int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *);
147void phyint_send(struct ip *, struct vif *, struct mbuf *);
148void send_packet(struct vif *, struct mbuf *);

--- 81 unchanged lines hidden (view full) ---

230
231/*
232 * Find a route for a given origin IP address and Multicast group address
233 * Type of service parameter to be added in the future!!!
234 * Statistics are updated by the caller if needed
235 * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses)
236 */
237static struct mfc *
141int get_api_support(struct mbuf *);
142int get_api_config(struct mbuf *);
143int socket_send(struct socket *, struct mbuf *,
144 struct sockaddr_in *);
145void expire_upcalls(void *);
146int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *);
147void phyint_send(struct ip *, struct vif *, struct mbuf *);
148void send_packet(struct vif *, struct mbuf *);

--- 81 unchanged lines hidden (view full) ---

230
231/*
232 * Find a route for a given origin IP address and Multicast group address
233 * Type of service parameter to be added in the future!!!
234 * Statistics are updated by the caller if needed
235 * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses)
236 */
237static struct mfc *
238mfc_find(struct in_addr *o, struct in_addr *g)
238mfc_find(unsigned int rtableid, struct in_addr *o, struct in_addr *g)
239{
240 struct mfc *rt;
241 u_int32_t hash;
242
239{
240 struct mfc *rt;
241 u_int32_t hash;
242
243 hash = MFCHASH(*o, *g);
244 LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
243 if (mfchashtbl[rtableid] == NULL)
244 return (NULL);
245
246 hash = MFCHASH(rtableid, *o, *g);
247 LIST_FOREACH(rt, &mfchashtbl[rtableid][hash], mfc_hash) {
245 if (in_hosteq(rt->mfc_origin, *o) &&
246 in_hosteq(rt->mfc_mcastgrp, *g) &&
247 (rt->mfc_stall == NULL))
248 break;
249 }
250
251 return (rt);
252}

--- 22 unchanged lines hidden (view full) ---

275} while (/*CONSTCOND*/ 0)
276
277/*
278 * Handle MRT setsockopt commands to modify the multicast routing tables.
279 */
280int
281ip_mrouter_set(struct socket *so, int optname, struct mbuf **mp)
282{
248 if (in_hosteq(rt->mfc_origin, *o) &&
249 in_hosteq(rt->mfc_mcastgrp, *g) &&
250 (rt->mfc_stall == NULL))
251 break;
252 }
253
254 return (rt);
255}

--- 22 unchanged lines hidden (view full) ---

278} while (/*CONSTCOND*/ 0)
279
280/*
281 * Handle MRT setsockopt commands to modify the multicast routing tables.
282 */
283int
284ip_mrouter_set(struct socket *so, int optname, struct mbuf **mp)
285{
286 struct inpcb *inp = sotoinpcb(so);
283 int error;
284
287 int error;
288
285 if (optname != MRT_INIT && so != ip_mrouter)
289 if (optname != MRT_INIT &&
290 so != ip_mrouter[inp->inp_rtableid])
286 error = ENOPROTOOPT;
287 else
288 switch (optname) {
289 case MRT_INIT:
290 error = ip_mrouter_init(so, *mp);
291 break;
292 case MRT_DONE:
291 error = ENOPROTOOPT;
292 else
293 switch (optname) {
294 case MRT_INIT:
295 error = ip_mrouter_init(so, *mp);
296 break;
297 case MRT_DONE:
293 error = ip_mrouter_done();
298 error = ip_mrouter_done(so);
294 break;
295 case MRT_ADD_VIF:
296 error = add_vif(so, *mp);
297 break;
298 case MRT_DEL_VIF:
299 error = del_vif(*mp);
300 break;
301 case MRT_ADD_MFC:
299 break;
300 case MRT_ADD_VIF:
301 error = add_vif(so, *mp);
302 break;
303 case MRT_DEL_VIF:
304 error = del_vif(*mp);
305 break;
306 case MRT_ADD_MFC:
302 error = add_mfc(*mp);
307 error = add_mfc(so, *mp);
303 break;
304 case MRT_DEL_MFC:
308 break;
309 case MRT_DEL_MFC:
305 error = del_mfc(*mp);
310 error = del_mfc(so, *mp);
306 break;
307#ifdef PIM
308 case MRT_ASSERT:
309 error = set_assert(*mp);
310 break;
311#endif
312 case MRT_API_CONFIG:
311 break;
312#ifdef PIM
313 case MRT_ASSERT:
314 error = set_assert(*mp);
315 break;
316#endif
317 case MRT_API_CONFIG:
313 error = set_api_config(*mp);
318 error = set_api_config(so, *mp);
314 break;
315 default:
316 error = ENOPROTOOPT;
317 break;
318 }
319
320 m_free(*mp);
321 return (error);
322}
323
324/*
325 * Handle MRT getsockopt commands
326 */
327int
328ip_mrouter_get(struct socket *so, int optname, struct mbuf **mp)
329{
319 break;
320 default:
321 error = ENOPROTOOPT;
322 break;
323 }
324
325 m_free(*mp);
326 return (error);
327}
328
329/*
330 * Handle MRT getsockopt commands
331 */
332int
333ip_mrouter_get(struct socket *so, int optname, struct mbuf **mp)
334{
335 struct inpcb *inp = sotoinpcb(so);
330 int error;
331
336 int error;
337
332 if (so != ip_mrouter)
338 if (so != ip_mrouter[inp->inp_rtableid])
333 error = ENOPROTOOPT;
334 else {
335 *mp = m_get(M_WAIT, MT_SOOPTS);
336
337 switch (optname) {
338 case MRT_VERSION:
339 error = get_version(*mp);
340 break;

--- 21 unchanged lines hidden (view full) ---

362}
363
364/*
365 * Handle ioctl commands to obtain information from the cache
366 */
367int
368mrt_ioctl(struct socket *so, u_long cmd, caddr_t data)
369{
339 error = ENOPROTOOPT;
340 else {
341 *mp = m_get(M_WAIT, MT_SOOPTS);
342
343 switch (optname) {
344 case MRT_VERSION:
345 error = get_version(*mp);
346 break;

--- 21 unchanged lines hidden (view full) ---

368}
369
370/*
371 * Handle ioctl commands to obtain information from the cache
372 */
373int
374mrt_ioctl(struct socket *so, u_long cmd, caddr_t data)
375{
376 struct inpcb *inp = sotoinpcb(so);
370 int error;
371
377 int error;
378
372 if (so != ip_mrouter)
379 if (so != ip_mrouter[inp->inp_rtableid])
373 error = EINVAL;
374 else
375 switch (cmd) {
376 case SIOCGETVIFCNT:
377 error = get_vif_cnt((struct sioc_vif_req *)data);
378 break;
379 case SIOCGETSGCNT:
380 error = EINVAL;
381 else
382 switch (cmd) {
383 case SIOCGETVIFCNT:
384 error = get_vif_cnt((struct sioc_vif_req *)data);
385 break;
386 case SIOCGETSGCNT:
380 error = get_sg_cnt((struct sioc_sg_req *)data);
387 error = get_sg_cnt(inp->inp_rtableid,
388 (struct sioc_sg_req *)data);
381 break;
382 default:
383 error = ENOTTY;
384 break;
385 }
386
387 return (error);
388}
389
390/*
391 * returns the packet, byte, rpf-failure count for the source group provided
392 */
393int
389 break;
390 default:
391 error = ENOTTY;
392 break;
393 }
394
395 return (error);
396}
397
398/*
399 * returns the packet, byte, rpf-failure count for the source group provided
400 */
401int
394get_sg_cnt(struct sioc_sg_req *req)
402get_sg_cnt(unsigned int rtableid, struct sioc_sg_req *req)
395{
396 int s;
397 struct mfc *rt;
398
399 s = splsoftnet();
403{
404 int s;
405 struct mfc *rt;
406
407 s = splsoftnet();
400 rt = mfc_find(&req->src, &req->grp);
408 rt = mfc_find(rtableid, &req->src, &req->grp);
401 if (rt == NULL) {
402 splx(s);
403 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
404 return (EADDRNOTAVAIL);
405 }
406 req->pktcnt = rt->mfc_pkt_cnt;
407 req->bytecnt = rt->mfc_byte_cnt;
408 req->wrong_if = rt->mfc_wrong_if;

--- 68 unchanged lines hidden (view full) ---

477}
478
479int
480mrt_sysctl_mfc(void *oldp, size_t *oldlenp)
481{
482 caddr_t where = oldp;
483 size_t needed, given;
484 u_long i;
409 if (rt == NULL) {
410 splx(s);
411 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
412 return (EADDRNOTAVAIL);
413 }
414 req->pktcnt = rt->mfc_pkt_cnt;
415 req->bytecnt = rt->mfc_byte_cnt;
416 req->wrong_if = rt->mfc_wrong_if;

--- 68 unchanged lines hidden (view full) ---

485}
486
487int
488mrt_sysctl_mfc(void *oldp, size_t *oldlenp)
489{
490 caddr_t where = oldp;
491 size_t needed, given;
492 u_long i;
493 unsigned int rtableid;
485 struct mfc *m;
486 struct mfcinfo minfo;
487
488 given = *oldlenp;
489 needed = 0;
494 struct mfc *m;
495 struct mfcinfo minfo;
496
497 given = *oldlenp;
498 needed = 0;
490 for (i = 0; mfchashtbl && i < MFCTBLSIZ; ++i) {
491 LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
492 minfo.mfc_origin = m->mfc_origin;
493 minfo.mfc_mcastgrp = m->mfc_mcastgrp;
494 minfo.mfc_parent = m->mfc_parent;
495 minfo.mfc_pkt_cnt = m->mfc_pkt_cnt;
496 minfo.mfc_byte_cnt = m->mfc_byte_cnt;
497 memcpy(minfo.mfc_ttls, m->mfc_ttls, MAXVIFS);
499 for (rtableid = 0; rtableid < RT_TABLEID_MAX; rtableid++) {
500 if (mfchashtbl[rtableid] == NULL)
501 continue;
498
502
499 needed += sizeof(minfo);
500 if (where && needed <= given) {
501 int error;
503 for (i = 0; i < MFCTBLSIZ; ++i) {
504 LIST_FOREACH(m, &mfchashtbl[rtableid][i], mfc_hash) {
505 minfo.mfc_origin = m->mfc_origin;
506 minfo.mfc_mcastgrp = m->mfc_mcastgrp;
507 minfo.mfc_parent = m->mfc_parent;
508 minfo.mfc_pkt_cnt = m->mfc_pkt_cnt;
509 minfo.mfc_byte_cnt = m->mfc_byte_cnt;
510 memcpy(minfo.mfc_ttls, m->mfc_ttls, MAXVIFS);
502
511
503 error = copyout(&minfo, where, sizeof(minfo));
504 if (error)
505 return (error);
506 where += sizeof(minfo);
512 needed += sizeof(minfo);
513 if (where && needed <= given) {
514 int error;
515
516 error = copyout(&minfo, where,
517 sizeof(minfo));
518 if (error)
519 return (error);
520 where += sizeof(minfo);
521 }
507 }
508 }
509 }
510 if (where) {
511 *oldlenp = needed;
512 if (given < needed)
513 return (ENOMEM);
514 } else
515 *oldlenp = (11 * needed) / 10;
516
517 return (0);
518}
519
520/*
521 * Enable multicast routing
522 */
523int
524ip_mrouter_init(struct socket *so, struct mbuf *m)
525{
522 }
523 }
524 }
525 if (where) {
526 *oldlenp = needed;
527 if (given < needed)
528 return (ENOMEM);
529 } else
530 *oldlenp = (11 * needed) / 10;
531
532 return (0);
533}
534
535/*
536 * Enable multicast routing
537 */
538int
539ip_mrouter_init(struct socket *so, struct mbuf *m)
540{
541 struct inpcb *inp = sotoinpcb(so);
542 unsigned int rtableid = inp->inp_rtableid;
526 int *v;
527
528 if (so->so_type != SOCK_RAW ||
529 so->so_proto->pr_protocol != IPPROTO_IGMP)
530 return (EOPNOTSUPP);
531
532 if (m == NULL || m->m_len < sizeof(int))
533 return (EINVAL);
534
535 v = mtod(m, int *);
536 if (*v != 1)
537 return (EINVAL);
538
543 int *v;
544
545 if (so->so_type != SOCK_RAW ||
546 so->so_proto->pr_protocol != IPPROTO_IGMP)
547 return (EOPNOTSUPP);
548
549 if (m == NULL || m->m_len < sizeof(int))
550 return (EINVAL);
551
552 v = mtod(m, int *);
553 if (*v != 1)
554 return (EINVAL);
555
539 if (ip_mrouter != NULL)
556 if (ip_mrouter[rtableid] != NULL)
540 return (EADDRINUSE);
541
557 return (EADDRINUSE);
558
542 ip_mrouter = so;
559 ip_mrouter[rtableid] = so;
543
560
544 mfchashtbl = hashinit(MFCTBLSIZ, M_MRTABLE, M_WAITOK, &mfchash);
545 arc4random_buf(&mfchashkey, sizeof(mfchashkey));
546 memset(nexpire, 0, sizeof(nexpire));
561 mfchashtbl[rtableid] =
562 hashinit(MFCTBLSIZ, M_MRTABLE, M_WAITOK, &mfchash[rtableid]);
563 arc4random_buf(&mfchashkey[rtableid], sizeof(mfchashkey[rtableid]));
564 memset(nexpire[rtableid], 0, sizeof(nexpire[rtableid]));
547
548#ifdef PIM
549 pim_assert = 0;
550#endif
551
552 timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
553 timeout_add_msec(&expire_upcalls_ch, EXPIRE_TIMEOUT);
554
555 return (0);
556}
557
558u_int32_t
565
566#ifdef PIM
567 pim_assert = 0;
568#endif
569
570 timeout_set(&expire_upcalls_ch, expire_upcalls, NULL);
571 timeout_add_msec(&expire_upcalls_ch, EXPIRE_TIMEOUT);
572
573 return (0);
574}
575
576u_int32_t
559_mfchash(struct in_addr o, struct in_addr g)
577_mfchash(unsigned int rtableid, struct in_addr o, struct in_addr g)
560{
561 SIPHASH_CTX ctx;
562
578{
579 SIPHASH_CTX ctx;
580
563 SipHash24_Init(&ctx, &mfchashkey);
581 SipHash24_Init(&ctx, &mfchashkey[rtableid]);
564 SipHash24_Update(&ctx, &o.s_addr, sizeof(o.s_addr));
565 SipHash24_Update(&ctx, &g.s_addr, sizeof(g.s_addr));
566
582 SipHash24_Update(&ctx, &o.s_addr, sizeof(o.s_addr));
583 SipHash24_Update(&ctx, &g.s_addr, sizeof(g.s_addr));
584
567 return (SipHash24_End(&ctx) & mfchash);
585 return (SipHash24_End(&ctx) & mfchash[rtableid]);
568}
569
570/*
571 * Disable multicast routing
572 */
573int
586}
587
588/*
589 * Disable multicast routing
590 */
591int
574ip_mrouter_done(void)
592ip_mrouter_done(struct socket *so)
575{
593{
594 struct inpcb *inp = sotoinpcb(so);
576 vifi_t vifi;
577 struct vif *vifp;
578 int i;
579 int s;
595 vifi_t vifi;
596 struct vif *vifp;
597 int i;
598 int s;
599 unsigned int rtableid = inp->inp_rtableid;
580
581 s = splsoftnet();
582
583 /* Clear out all the vifs currently in use. */
584 for (vifi = 0; vifi < numvifs; vifi++) {
585 vifp = &viftable[vifi];
586 if (!in_nullhost(vifp->v_lcl_addr))
587 reset_vif(vifp);

--- 9 unchanged lines hidden (view full) ---

597 timeout_del(&expire_upcalls_ch);
598
599 /*
600 * Free all multicast forwarding cache entries.
601 */
602 for (i = 0; i < MFCTBLSIZ; i++) {
603 struct mfc *rt, *nrt;
604
600
601 s = splsoftnet();
602
603 /* Clear out all the vifs currently in use. */
604 for (vifi = 0; vifi < numvifs; vifi++) {
605 vifp = &viftable[vifi];
606 if (!in_nullhost(vifp->v_lcl_addr))
607 reset_vif(vifp);

--- 9 unchanged lines hidden (view full) ---

617 timeout_del(&expire_upcalls_ch);
618
619 /*
620 * Free all multicast forwarding cache entries.
621 */
622 for (i = 0; i < MFCTBLSIZ; i++) {
623 struct mfc *rt, *nrt;
624
605 for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
625 for (rt = LIST_FIRST(&mfchashtbl[rtableid][i]); rt; rt = nrt) {
606 nrt = LIST_NEXT(rt, mfc_hash);
607
608 expire_mfc(rt);
609 }
610 }
611
626 nrt = LIST_NEXT(rt, mfc_hash);
627
628 expire_mfc(rt);
629 }
630 }
631
612 memset(nexpire, 0, sizeof(nexpire));
613 hashfree(mfchashtbl, MFCTBLSIZ, M_MRTABLE);
614 mfchashtbl = NULL;
632 memset(nexpire[rtableid], 0, sizeof(nexpire[rtableid]));
633 hashfree(mfchashtbl[rtableid], MFCTBLSIZ, M_MRTABLE);
634 mfchashtbl[rtableid] = NULL;
615
635
616 ip_mrouter = NULL;
636 ip_mrouter[rtableid] = NULL;
617
618 splx(s);
619
620 return (0);
621}
622
623void
624ip_mrouter_detach(struct ifnet *ifp)

--- 7 unchanged lines hidden (view full) ---

632 for (vifi = 0; vifi < numvifs; vifi++) {
633 vifp = &viftable[vifi];
634 if (vifp->v_ifp == ifp)
635 reset_vif(vifp);
636 }
637 for (i = 0; i < MFCTBLSIZ; i++) {
638 if (nexpire[i] == 0)
639 continue;
637
638 splx(s);
639
640 return (0);
641}
642
643void
644ip_mrouter_detach(struct ifnet *ifp)

--- 7 unchanged lines hidden (view full) ---

652 for (vifi = 0; vifi < numvifs; vifi++) {
653 vifp = &viftable[vifi];
654 if (vifp->v_ifp == ifp)
655 reset_vif(vifp);
656 }
657 for (i = 0; i < MFCTBLSIZ; i++) {
658 if (nexpire[i] == 0)
659 continue;
640 LIST_FOREACH(rt, &mfchashtbl[i], mfc_hash) {
660 LIST_FOREACH(rt, &mfchashtbl[ifp->if_rdomain][i], mfc_hash) {
641 for (rte = rt->mfc_stall; rte; rte = rte->next) {
642 if (rte->ifp == ifp)
643 rte->ifp = NULL;
644 }
645 }
646 }
647}
648

--- 37 unchanged lines hidden (view full) ---

686 return (0);
687}
688#endif
689
690/*
691 * Configure API capabilities
692 */
693int
661 for (rte = rt->mfc_stall; rte; rte = rte->next) {
662 if (rte->ifp == ifp)
663 rte->ifp = NULL;
664 }
665 }
666 }
667}
668

--- 37 unchanged lines hidden (view full) ---

706 return (0);
707}
708#endif
709
710/*
711 * Configure API capabilities
712 */
713int
694set_api_config(struct mbuf *m)
714set_api_config(struct socket *so, struct mbuf *m)
695{
715{
716 struct inpcb *inp = sotoinpcb(so);
696 int i;
697 u_int32_t *apival;
717 int i;
718 u_int32_t *apival;
719 unsigned int rtableid = inp->inp_rtableid;
698
699 if (m == NULL || m->m_len < sizeof(u_int32_t))
700 return (EINVAL);
701
702 apival = mtod(m, u_int32_t *);
703
704 /*
705 * We can set the API capabilities only if it is the first operation

--- 8 unchanged lines hidden (view full) ---

714 }
715#ifdef PIM
716 if (pim_assert) {
717 *apival = 0;
718 return (EPERM);
719 }
720#endif
721 for (i = 0; i < MFCTBLSIZ; i++) {
720
721 if (m == NULL || m->m_len < sizeof(u_int32_t))
722 return (EINVAL);
723
724 apival = mtod(m, u_int32_t *);
725
726 /*
727 * We can set the API capabilities only if it is the first operation

--- 8 unchanged lines hidden (view full) ---

736 }
737#ifdef PIM
738 if (pim_assert) {
739 *apival = 0;
740 return (EPERM);
741 }
742#endif
743 for (i = 0; i < MFCTBLSIZ; i++) {
722 if (LIST_FIRST(&mfchashtbl[i]) != NULL) {
744 if (mfchashtbl[rtableid] == NULL)
745 break;
746
747 if (LIST_FIRST(&mfchashtbl[rtableid][i]) != NULL) {
723 *apival = 0;
724 return (EPERM);
725 }
726 }
727
728 mrt_api_config = *apival & mrt_api_support;
729 *apival = mrt_api_config;
730

--- 201 unchanged lines hidden (view full) ---

932
933void
934vif_delete(struct ifnet *ifp)
935{
936 int i;
937 struct vif *vifp;
938 struct mfc *rt;
939 struct rtdetq *rte;
748 *apival = 0;
749 return (EPERM);
750 }
751 }
752
753 mrt_api_config = *apival & mrt_api_support;
754 *apival = mrt_api_config;
755

--- 201 unchanged lines hidden (view full) ---

957
958void
959vif_delete(struct ifnet *ifp)
960{
961 int i;
962 struct vif *vifp;
963 struct mfc *rt;
964 struct rtdetq *rte;
965 unsigned int rtableid = ifp->if_rdomain;
940
941 for (i = 0; i < numvifs; i++) {
942 vifp = &viftable[i];
943 if (vifp->v_ifp == ifp)
944 memset(vifp, 0, sizeof(*vifp));
945 }
946
947 for (i = numvifs; i > 0; i--)
948 if (!in_nullhost(viftable[i - 1].v_lcl_addr))
949 break;
950 numvifs = i;
951
966
967 for (i = 0; i < numvifs; i++) {
968 vifp = &viftable[i];
969 if (vifp->v_ifp == ifp)
970 memset(vifp, 0, sizeof(*vifp));
971 }
972
973 for (i = numvifs; i > 0; i--)
974 if (!in_nullhost(viftable[i - 1].v_lcl_addr))
975 break;
976 numvifs = i;
977
978 if (ip_mrouter[rtableid] == NULL)
979 return;
980
952 for (i = 0; i < MFCTBLSIZ; i++) {
981 for (i = 0; i < MFCTBLSIZ; i++) {
953 if (nexpire[i] == 0)
982 if (nexpire[rtableid][i] == 0)
954 continue;
983 continue;
955 LIST_FOREACH(rt, &mfchashtbl[i], mfc_hash) {
984
985 LIST_FOREACH(rt, &mfchashtbl[rtableid][i], mfc_hash) {
956 for (rte = rt->mfc_stall; rte; rte = rte->next) {
957 if (rte->ifp == ifp)
958 rte->ifp = NULL;
959 }
960 }
961 }
962}
963

--- 50 unchanged lines hidden (view full) ---

1014 LIST_REMOVE(rt, mfc_hash);
1015 free(rt, M_MRTABLE, 0);
1016}
1017
1018/*
1019 * Add an mfc entry
1020 */
1021int
986 for (rte = rt->mfc_stall; rte; rte = rte->next) {
987 if (rte->ifp == ifp)
988 rte->ifp = NULL;
989 }
990 }
991 }
992}
993

--- 50 unchanged lines hidden (view full) ---

1044 LIST_REMOVE(rt, mfc_hash);
1045 free(rt, M_MRTABLE, 0);
1046}
1047
1048/*
1049 * Add an mfc entry
1050 */
1051int
1022add_mfc(struct mbuf *m)
1052add_mfc(struct socket *so, struct mbuf *m)
1023{
1053{
1054 struct inpcb *inp = sotoinpcb(so);
1024 struct mfcctl2 mfcctl2;
1025 struct mfcctl2 *mfccp;
1026 struct mfc *rt;
1027 u_int32_t hash = 0;
1028 struct rtdetq *rte, *nrte;
1029 u_short nstl;
1030 int s;
1031 int mfcctl_size = sizeof(struct mfcctl);
1055 struct mfcctl2 mfcctl2;
1056 struct mfcctl2 *mfccp;
1057 struct mfc *rt;
1058 u_int32_t hash = 0;
1059 struct rtdetq *rte, *nrte;
1060 u_short nstl;
1061 int s;
1062 int mfcctl_size = sizeof(struct mfcctl);
1063 unsigned int rtableid = inp->inp_rtableid;
1032
1033 if (mrt_api_config & MRT_API_FLAGS_ALL)
1034 mfcctl_size = sizeof(struct mfcctl2);
1035
1036 if (m == NULL || m->m_len < mfcctl_size)
1037 return (EINVAL);
1038
1039 /*

--- 6 unchanged lines hidden (view full) ---

1046 struct mfcctl *mp = mtod(m, struct mfcctl *);
1047 bcopy(mp, (caddr_t)&mfcctl2, sizeof(*mp));
1048 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0,
1049 sizeof(mfcctl2) - sizeof(struct mfcctl));
1050 }
1051 mfccp = &mfcctl2;
1052
1053 s = splsoftnet();
1064
1065 if (mrt_api_config & MRT_API_FLAGS_ALL)
1066 mfcctl_size = sizeof(struct mfcctl2);
1067
1068 if (m == NULL || m->m_len < mfcctl_size)
1069 return (EINVAL);
1070
1071 /*

--- 6 unchanged lines hidden (view full) ---

1078 struct mfcctl *mp = mtod(m, struct mfcctl *);
1079 bcopy(mp, (caddr_t)&mfcctl2, sizeof(*mp));
1080 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0,
1081 sizeof(mfcctl2) - sizeof(struct mfcctl));
1082 }
1083 mfccp = &mfcctl2;
1084
1085 s = splsoftnet();
1054 rt = mfc_find(&mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
1086 /* No hash table allocated for this. */
1087 if (mfchashtbl[rtableid] == NULL) {
1088 splx(s);
1089 return (0);
1090 }
1055
1091
1092 rt = mfc_find(rtableid, &mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
1093
1056 /* If an entry already exists, just update the fields */
1057 if (rt) {
1058 update_mfc_params(rt, mfccp);
1059 splx(s);
1060 return (0);
1061 }
1062
1063 /*
1064 * Find the entry for which the upcall was made and update
1065 */
1066 nstl = 0;
1094 /* If an entry already exists, just update the fields */
1095 if (rt) {
1096 update_mfc_params(rt, mfccp);
1097 splx(s);
1098 return (0);
1099 }
1100
1101 /*
1102 * Find the entry for which the upcall was made and update
1103 */
1104 nstl = 0;
1067 hash = MFCHASH(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp);
1068 LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
1105 hash = MFCHASH(rtableid, mfccp->mfcc_origin, mfccp->mfcc_mcastgrp);
1106 LIST_FOREACH(rt, &mfchashtbl[rtableid][hash], mfc_hash) {
1069 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1070 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) &&
1071 rt->mfc_stall != NULL) {
1072 if (nstl++) {
1073 log(LOG_ERR, "add_mfc %s o %x g %x "
1074 "p %x dbx %p\n",
1075 "multiple kernel entries",
1076 ntohl(mfccp->mfcc_origin.s_addr),
1077 ntohl(mfccp->mfcc_mcastgrp.s_addr),
1078 mfccp->mfcc_parent, rt->mfc_stall);
1079 }
1080
1081 rte = rt->mfc_stall;
1082 init_mfc_params(rt, mfccp);
1083 rt->mfc_stall = NULL;
1084
1085 rt->mfc_expire = 0; /* Don't clean this guy up */
1107 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1108 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) &&
1109 rt->mfc_stall != NULL) {
1110 if (nstl++) {
1111 log(LOG_ERR, "add_mfc %s o %x g %x "
1112 "p %x dbx %p\n",
1113 "multiple kernel entries",
1114 ntohl(mfccp->mfcc_origin.s_addr),
1115 ntohl(mfccp->mfcc_mcastgrp.s_addr),
1116 mfccp->mfcc_parent, rt->mfc_stall);
1117 }
1118
1119 rte = rt->mfc_stall;
1120 init_mfc_params(rt, mfccp);
1121 rt->mfc_stall = NULL;
1122
1123 rt->mfc_expire = 0; /* Don't clean this guy up */
1086 nexpire[hash]--;
1124 nexpire[rtableid][hash]--;
1087
1088 /* free packets Qed at the end of this entry */
1089 for (; rte != NULL; rte = nrte) {
1090 nrte = rte->next;
1091 if (rte->ifp) {
1092 ip_mdq(rte->m, rte->ifp, rt);
1093 }
1094 m_freem(rte->m);

--- 4 unchanged lines hidden (view full) ---

1099
1100 /*
1101 * It is possible that an entry is being inserted without an upcall
1102 */
1103 if (nstl == 0) {
1104 /*
1105 * No mfc; make a new one
1106 */
1125
1126 /* free packets Qed at the end of this entry */
1127 for (; rte != NULL; rte = nrte) {
1128 nrte = rte->next;
1129 if (rte->ifp) {
1130 ip_mdq(rte->m, rte->ifp, rt);
1131 }
1132 m_freem(rte->m);

--- 4 unchanged lines hidden (view full) ---

1137
1138 /*
1139 * It is possible that an entry is being inserted without an upcall
1140 */
1141 if (nstl == 0) {
1142 /*
1143 * No mfc; make a new one
1144 */
1107 LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
1145 LIST_FOREACH(rt, &mfchashtbl[rtableid][hash], mfc_hash) {
1108 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1109 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp)) {
1110 init_mfc_params(rt, mfccp);
1111 if (rt->mfc_expire)
1146 if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
1147 in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp)) {
1148 init_mfc_params(rt, mfccp);
1149 if (rt->mfc_expire)
1112 nexpire[hash]--;
1150 nexpire[rtableid][hash]--;
1113 rt->mfc_expire = 0;
1114 break; /* XXX */
1115 }
1116 }
1117 if (rt == NULL) { /* no upcall, so make a new entry */
1118 rt = malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1119 if (rt == NULL) {
1120 splx(s);
1121 return (ENOBUFS);
1122 }
1123
1124 init_mfc_params(rt, mfccp);
1125 rt->mfc_expire = 0;
1126 rt->mfc_stall = NULL;
1127
1128 /* insert new entry at head of hash chain */
1151 rt->mfc_expire = 0;
1152 break; /* XXX */
1153 }
1154 }
1155 if (rt == NULL) { /* no upcall, so make a new entry */
1156 rt = malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
1157 if (rt == NULL) {
1158 splx(s);
1159 return (ENOBUFS);
1160 }
1161
1162 init_mfc_params(rt, mfccp);
1163 rt->mfc_expire = 0;
1164 rt->mfc_stall = NULL;
1165
1166 /* insert new entry at head of hash chain */
1129 LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
1167 LIST_INSERT_HEAD(&mfchashtbl[rtableid][hash], rt, mfc_hash);
1130 }
1131 }
1132
1133 splx(s);
1134 return (0);
1135}
1136
1137/*
1138 * Delete an mfc entry
1139 */
1140int
1168 }
1169 }
1170
1171 splx(s);
1172 return (0);
1173}
1174
1175/*
1176 * Delete an mfc entry
1177 */
1178int
1141del_mfc(struct mbuf *m)
1179del_mfc(struct socket *so, struct mbuf *m)
1142{
1180{
1181 struct inpcb *inp = sotoinpcb(so);
1143 struct mfcctl2 mfcctl2;
1144 struct mfcctl2 *mfccp;
1145 struct mfc *rt;
1146 int s;
1147 int mfcctl_size = sizeof(struct mfcctl);
1148 struct mfcctl *mp = mtod(m, struct mfcctl *);
1182 struct mfcctl2 mfcctl2;
1183 struct mfcctl2 *mfccp;
1184 struct mfc *rt;
1185 int s;
1186 int mfcctl_size = sizeof(struct mfcctl);
1187 struct mfcctl *mp = mtod(m, struct mfcctl *);
1188 unsigned int rtableid = inp->inp_rtableid;
1149
1150 /*
1151 * XXX: for deleting MFC entries the information in entries
1152 * of size "struct mfcctl" is sufficient.
1153 */
1154
1155 if (m == NULL || m->m_len < mfcctl_size)
1156 return (EINVAL);
1157
1158 bcopy(mp, (caddr_t)&mfcctl2, sizeof(*mp));
1159 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0,
1160 sizeof(mfcctl2) - sizeof(struct mfcctl));
1161
1162 mfccp = &mfcctl2;
1163
1164 s = splsoftnet();
1165
1189
1190 /*
1191 * XXX: for deleting MFC entries the information in entries
1192 * of size "struct mfcctl" is sufficient.
1193 */
1194
1195 if (m == NULL || m->m_len < mfcctl_size)
1196 return (EINVAL);
1197
1198 bcopy(mp, (caddr_t)&mfcctl2, sizeof(*mp));
1199 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0,
1200 sizeof(mfcctl2) - sizeof(struct mfcctl));
1201
1202 mfccp = &mfcctl2;
1203
1204 s = splsoftnet();
1205
1166 rt = mfc_find(&mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
1206 rt = mfc_find(rtableid, &mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
1167 if (rt == NULL) {
1168 splx(s);
1169 return (EADDRNOTAVAIL);
1170 }
1171
1172 LIST_REMOVE(rt, mfc_hash);
1173 free(rt, M_MRTABLE, 0);
1174

--- 32 unchanged lines hidden (view full) ---

1207ip_mforward(struct mbuf *m, struct ifnet *ifp)
1208{
1209 struct ip *ip = mtod(m, struct ip *);
1210 struct mfc *rt;
1211 static int srctun = 0;
1212 struct mbuf *mm;
1213 int s;
1214 vifi_t vifi;
1207 if (rt == NULL) {
1208 splx(s);
1209 return (EADDRNOTAVAIL);
1210 }
1211
1212 LIST_REMOVE(rt, mfc_hash);
1213 free(rt, M_MRTABLE, 0);
1214

--- 32 unchanged lines hidden (view full) ---

1247ip_mforward(struct mbuf *m, struct ifnet *ifp)
1248{
1249 struct ip *ip = mtod(m, struct ip *);
1250 struct mfc *rt;
1251 static int srctun = 0;
1252 struct mbuf *mm;
1253 int s;
1254 vifi_t vifi;
1255 unsigned int rtableid = ifp->if_rdomain;
1215
1216 if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
1217 ((u_char *)(ip + 1))[1] != IPOPT_LSRR) {
1218 /*
1219 * Packet arrived via a physical interface or
1220 * an encapsulated tunnel or a register_vif.
1221 */
1222 } else {

--- 15 unchanged lines hidden (view full) ---

1238 if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr))
1239 return (0);
1240
1241 /*
1242 * Determine forwarding vifs from the forwarding cache table
1243 */
1244 s = splsoftnet();
1245 ++mrtstat.mrts_mfc_lookups;
1256
1257 if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
1258 ((u_char *)(ip + 1))[1] != IPOPT_LSRR) {
1259 /*
1260 * Packet arrived via a physical interface or
1261 * an encapsulated tunnel or a register_vif.
1262 */
1263 } else {

--- 15 unchanged lines hidden (view full) ---

1279 if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr))
1280 return (0);
1281
1282 /*
1283 * Determine forwarding vifs from the forwarding cache table
1284 */
1285 s = splsoftnet();
1286 ++mrtstat.mrts_mfc_lookups;
1246 rt = mfc_find(&ip->ip_src, &ip->ip_dst);
1287 rt = mfc_find(rtableid, &ip->ip_src, &ip->ip_dst);
1247
1248 /* Entry exists, so forward if necessary */
1249 if (rt != NULL) {
1250 splx(s);
1251 return (ip_mdq(m, ifp, rt));
1252 } else {
1253 /*
1254 * If we don't have a route for packet's origin,

--- 22 unchanged lines hidden (view full) ---

1277 M_PULLUP(mb0, hlen);
1278 if (mb0 == NULL) {
1279 free(rte, M_MRTABLE, 0);
1280 splx(s);
1281 return (ENOBUFS);
1282 }
1283
1284 /* is there an upcall waiting for this flow? */
1288
1289 /* Entry exists, so forward if necessary */
1290 if (rt != NULL) {
1291 splx(s);
1292 return (ip_mdq(m, ifp, rt));
1293 } else {
1294 /*
1295 * If we don't have a route for packet's origin,

--- 22 unchanged lines hidden (view full) ---

1318 M_PULLUP(mb0, hlen);
1319 if (mb0 == NULL) {
1320 free(rte, M_MRTABLE, 0);
1321 splx(s);
1322 return (ENOBUFS);
1323 }
1324
1325 /* is there an upcall waiting for this flow? */
1285 hash = MFCHASH(ip->ip_src, ip->ip_dst);
1286 LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
1326 hash = MFCHASH(rtableid, ip->ip_src, ip->ip_dst);
1327 LIST_FOREACH(rt, &mfchashtbl[rtableid][hash], mfc_hash) {
1287 if (in_hosteq(ip->ip_src, rt->mfc_origin) &&
1288 in_hosteq(ip->ip_dst, rt->mfc_mcastgrp) &&
1289 rt->mfc_stall != NULL)
1290 break;
1291 }
1292
1293 if (rt == NULL) {
1294 int i;

--- 31 unchanged lines hidden (view full) ---

1326 im = mtod(mm, struct igmpmsg *);
1327 im->im_msgtype = IGMPMSG_NOCACHE;
1328 im->im_mbz = 0;
1329 im->im_vif = vifi;
1330
1331 mrtstat.mrts_upcalls++;
1332
1333 sin.sin_addr = ip->ip_src;
1328 if (in_hosteq(ip->ip_src, rt->mfc_origin) &&
1329 in_hosteq(ip->ip_dst, rt->mfc_mcastgrp) &&
1330 rt->mfc_stall != NULL)
1331 break;
1332 }
1333
1334 if (rt == NULL) {
1335 int i;

--- 31 unchanged lines hidden (view full) ---

1367 im = mtod(mm, struct igmpmsg *);
1368 im->im_msgtype = IGMPMSG_NOCACHE;
1369 im->im_mbz = 0;
1370 im->im_vif = vifi;
1371
1372 mrtstat.mrts_upcalls++;
1373
1374 sin.sin_addr = ip->ip_src;
1334 if (socket_send(ip_mrouter, mm, &sin) < 0) {
1375 if (socket_send(ip_mrouter[rtableid], mm, &sin) < 0) {
1335 log(LOG_WARNING, "ip_mforward: ip_mrouter "
1336 "socket queue full\n");
1337 ++mrtstat.mrts_upq_sockfull;
1338 fail1:
1339 free(rt, M_MRTABLE, 0);
1340 fail:
1341 free(rte, M_MRTABLE, 0);
1342 m_freem(mb0);
1343 splx(s);
1344 return (ENOBUFS);
1345 }
1346
1347 /* insert new entry at head of hash chain */
1348 rt->mfc_origin = ip->ip_src;
1349 rt->mfc_mcastgrp = ip->ip_dst;
1350 rt->mfc_pkt_cnt = 0;
1351 rt->mfc_byte_cnt = 0;
1352 rt->mfc_wrong_if = 0;
1353 rt->mfc_expire = UPCALL_EXPIRE;
1376 log(LOG_WARNING, "ip_mforward: ip_mrouter "
1377 "socket queue full\n");
1378 ++mrtstat.mrts_upq_sockfull;
1379 fail1:
1380 free(rt, M_MRTABLE, 0);
1381 fail:
1382 free(rte, M_MRTABLE, 0);
1383 m_freem(mb0);
1384 splx(s);
1385 return (ENOBUFS);
1386 }
1387
1388 /* insert new entry at head of hash chain */
1389 rt->mfc_origin = ip->ip_src;
1390 rt->mfc_mcastgrp = ip->ip_dst;
1391 rt->mfc_pkt_cnt = 0;
1392 rt->mfc_byte_cnt = 0;
1393 rt->mfc_wrong_if = 0;
1394 rt->mfc_expire = UPCALL_EXPIRE;
1354 nexpire[hash]++;
1395 nexpire[rtableid][hash]++;
1355 for (i = 0; i < numvifs; i++) {
1356 rt->mfc_ttls[i] = 0;
1357 rt->mfc_flags[i] = 0;
1358 }
1359 rt->mfc_parent = -1;
1360
1361 /* clear the RP address */
1362 rt->mfc_rp = zeroin_addr;
1363
1364 /* link into table */
1396 for (i = 0; i < numvifs; i++) {
1397 rt->mfc_ttls[i] = 0;
1398 rt->mfc_flags[i] = 0;
1399 }
1400 rt->mfc_parent = -1;
1401
1402 /* clear the RP address */
1403 rt->mfc_rp = zeroin_addr;
1404
1405 /* link into table */
1365 LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
1406 LIST_INSERT_HEAD(&mfchashtbl[rtableid][hash], rt, mfc_hash);
1366 /* Add this entry to the end of the queue */
1367 rt->mfc_stall = rte;
1368 } else {
1369 /* determine if q has overflowed */
1370 struct rtdetq **p;
1371 int npkts = 0;
1372
1373 /*

--- 27 unchanged lines hidden (view full) ---

1401
1402
1403/*ARGSUSED*/
1404void
1405expire_upcalls(void *v)
1406{
1407 int i;
1408 int s;
1407 /* Add this entry to the end of the queue */
1408 rt->mfc_stall = rte;
1409 } else {
1410 /* determine if q has overflowed */
1411 struct rtdetq **p;
1412 int npkts = 0;
1413
1414 /*

--- 27 unchanged lines hidden (view full) ---

1442
1443
1444/*ARGSUSED*/
1445void
1446expire_upcalls(void *v)
1447{
1448 int i;
1449 int s;
1450 unsigned int rtableid;
1409
1410 s = splsoftnet();
1411
1412 for (i = 0; i < MFCTBLSIZ; i++) {
1413 struct mfc *rt, *nrt;
1414
1451
1452 s = splsoftnet();
1453
1454 for (i = 0; i < MFCTBLSIZ; i++) {
1455 struct mfc *rt, *nrt;
1456
1415 if (nexpire[i] == 0)
1457 if (nexpire[rtableid][i] == 0)
1416 continue;
1417
1458 continue;
1459
1418 for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
1419 nrt = LIST_NEXT(rt, mfc_hash);
1420
1421 if (rt->mfc_expire == 0 || --rt->mfc_expire > 0)
1460 for (rtableid = 0; rtableid < RT_TABLEID_MAX; rtableid++) {
1461 if (mfchashtbl[rtableid] == NULL)
1422 continue;
1462 continue;
1423 nexpire[i]--;
1424
1463
1425 ++mrtstat.mrts_cache_cleanups;
1426 expire_mfc(rt);
1464 for (rt = LIST_FIRST(&mfchashtbl[rtableid][i]); rt;
1465 rt = nrt) {
1466 nrt = LIST_NEXT(rt, mfc_hash);
1467
1468 if (rt->mfc_expire == 0 || --rt->mfc_expire > 0)
1469 continue;
1470 nexpire[rtableid][i]--;
1471
1472 ++mrtstat.mrts_cache_cleanups;
1473 expire_mfc(rt);
1474 }
1427 }
1428 }
1429
1430 splx(s);
1431 timeout_add_msec(&expire_upcalls_ch, EXPIRE_TIMEOUT);
1432}
1433
1434/*

--- 65 unchanged lines hidden (view full) ---

1500 im = mtod(mm, struct igmpmsg *);
1501 im->im_msgtype = IGMPMSG_WRONGVIF;
1502 im->im_mbz = 0;
1503 im->im_vif = vifi;
1504
1505 mrtstat.mrts_upcalls++;
1506
1507 sin.sin_addr = im->im_src;
1475 }
1476 }
1477
1478 splx(s);
1479 timeout_add_msec(&expire_upcalls_ch, EXPIRE_TIMEOUT);
1480}
1481
1482/*

--- 65 unchanged lines hidden (view full) ---

1548 im = mtod(mm, struct igmpmsg *);
1549 im->im_msgtype = IGMPMSG_WRONGVIF;
1550 im->im_mbz = 0;
1551 im->im_vif = vifi;
1552
1553 mrtstat.mrts_upcalls++;
1554
1555 sin.sin_addr = im->im_src;
1508 if (socket_send(ip_mrouter, mm, &sin) < 0) {
1556 if (socket_send(ip_mrouter[rtableid], mm,
1557 &sin) < 0) {
1509 log(LOG_WARNING, "ip_mforward: "
1510 "ip_mrouter socket queue full\n");
1511 ++mrtstat.mrts_upq_sockfull;
1512 return (ENOBUFS);
1513 }
1514 }
1515 }
1516#endif

--- 182 unchanged lines hidden (view full) ---

1699 im->im_vif = vifp - viftable;
1700 im->im_src = ip->ip_src;
1701 im->im_dst = ip->ip_dst;
1702
1703 k_igmpsrc.sin_addr = ip->ip_src;
1704
1705 mrtstat.mrts_upcalls++;
1706
1558 log(LOG_WARNING, "ip_mforward: "
1559 "ip_mrouter socket queue full\n");
1560 ++mrtstat.mrts_upq_sockfull;
1561 return (ENOBUFS);
1562 }
1563 }
1564 }
1565#endif

--- 182 unchanged lines hidden (view full) ---

1748 im->im_vif = vifp - viftable;
1749 im->im_src = ip->ip_src;
1750 im->im_dst = ip->ip_dst;
1751
1752 k_igmpsrc.sin_addr = ip->ip_src;
1753
1754 mrtstat.mrts_upcalls++;
1755
1707 if (socket_send(ip_mrouter, mb_first, &k_igmpsrc) < 0) {
1756 if (socket_send(ip_mrouter[rtableid], mb_first, &k_igmpsrc) < 0) {
1708 ++mrtstat.mrts_upq_sockfull;
1709 return (ENOBUFS);
1710 }
1711
1712 /* Keep statistics */
1713 pimstat.pims_snd_registers_msgs++;
1714 pimstat.pims_snd_registers_bytes += len;
1715

--- 310 unchanged lines hidden ---
1757 ++mrtstat.mrts_upq_sockfull;
1758 return (ENOBUFS);
1759 }
1760
1761 /* Keep statistics */
1762 pimstat.pims_snd_registers_msgs++;
1763 pimstat.pims_snd_registers_bytes += len;
1764

--- 310 unchanged lines hidden ---