if_gif.c (a4ed727666b8a83c4f019b03bd4e9ac547c2b866) if_gif.c (c26230adeeac53e72cd5bc692504003894f2b3c3)
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

441}
442
443static void
444gif_qflush(struct ifnet *ifp __unused)
445{
446
447}
448
1/*-
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

441}
442
443static void
444gif_qflush(struct ifnet *ifp __unused)
445{
446
447}
448
449int
450gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
451 struct route *ro)
449#define MTAG_GIF 1080679712
450static int
451gif_check_nesting(struct ifnet *ifp, struct mbuf *m)
452{
453 struct m_tag *mtag;
452{
453 struct m_tag *mtag;
454 uint32_t af;
455 int gif_called;
456 int error = 0;
457#ifdef MAC
458 error = mac_ifnet_check_transmit(ifp, m);
459 if (error)
460 goto err;
461#endif
462 if ((ifp->if_flags & IFF_MONITOR) != 0 ||
463 (ifp->if_flags & IFF_UP) == 0) {
464 error = ENETDOWN;
465 goto err;
466 }
454 int count;
467
468 /*
469 * gif may cause infinite recursion calls when misconfigured.
470 * We'll prevent this by detecting loops.
471 *
472 * High nesting level may cause stack exhaustion.
473 * We'll prevent this by introducing upper limit.
474 */
455
456 /*
457 * gif may cause infinite recursion calls when misconfigured.
458 * We'll prevent this by detecting loops.
459 *
460 * High nesting level may cause stack exhaustion.
461 * We'll prevent this by introducing upper limit.
462 */
475 gif_called = 1;
476 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL);
477 while (mtag != NULL) {
463 count = 1;
464 mtag = NULL;
465 while ((mtag = m_tag_locate(m, MTAG_GIF, 0, mtag)) != NULL) {
478 if (*(struct ifnet **)(mtag + 1) == ifp) {
466 if (*(struct ifnet **)(mtag + 1) == ifp) {
479 log(LOG_NOTICE,
480 "gif_output: loop detected on %s\n",
481 (*(struct ifnet **)(mtag + 1))->if_xname);
482 error = EIO; /* is there better errno? */
483 goto err;
467 log(LOG_NOTICE, "%s: loop detected\n", ifp->if_xname);
468 return (EIO);
484 }
469 }
485 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag);
486 gif_called++;
470 count++;
487 }
471 }
488 if (gif_called > V_max_gif_nesting) {
472 if (count > V_max_gif_nesting) {
489 log(LOG_NOTICE,
473 log(LOG_NOTICE,
490 "gif_output: recursively called too many times(%d)\n",
491 gif_called);
492 error = EIO; /* is there better errno? */
493 goto err;
474 "%s: if_output recursively called too many times(%d)\n",
475 if_name(ifp), count);
476 return (EIO);
494 }
477 }
495 mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *),
496 M_NOWAIT);
497 if (mtag == NULL) {
498 error = ENOMEM;
499 goto err;
500 }
478 mtag = m_tag_alloc(MTAG_GIF, 0, sizeof(struct ifnet *), M_NOWAIT);
479 if (mtag == NULL)
480 return (ENOMEM);
501 *(struct ifnet **)(mtag + 1) = ifp;
502 m_tag_prepend(m, mtag);
481 *(struct ifnet **)(mtag + 1) = ifp;
482 m_tag_prepend(m, mtag);
483 return (0);
484}
503
485
486int
487gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
488 struct route *ro)
489{
490 uint32_t af;
491 int error = 0;
492#ifdef MAC
493 error = mac_ifnet_check_transmit(ifp, m);
494 if (error)
495 goto err;
496#endif
497 if ((ifp->if_flags & IFF_MONITOR) != 0 ||
498 (ifp->if_flags & IFF_UP) == 0) {
499 error = ENETDOWN;
500 goto err;
501 }
502
503 error = gif_check_nesting(ifp, m);
504 if (error != 0)
505 goto err;
504 m->m_flags &= ~(M_BCAST|M_MCAST);
505 if (dst->sa_family == AF_UNSPEC)
506 bcopy(dst->sa_data, &af, sizeof(af));
507 else
508 af = dst->sa_family;
509 if (ifp->if_bridge)
510 af = AF_LINK;
511 /*

--- 578 unchanged lines hidden ---
506 m->m_flags &= ~(M_BCAST|M_MCAST);
507 if (dst->sa_family == AF_UNSPEC)
508 bcopy(dst->sa_data, &af, sizeof(af));
509 else
510 af = dst->sa_family;
511 if (ifp->if_bridge)
512 af = AF_LINK;
513 /*

--- 578 unchanged lines hidden ---