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 --- |