| 502 | } |
| 503 | |
| 504 | int |
| 505 | gre_input(struct mbuf *m, int off, int proto, void *arg) |
| 506 | { |
| 507 | struct gre_softc *sc = arg; |
| 508 | struct grehdr *gh; |
| 509 | struct ifnet *ifp; |
| 510 | uint32_t *opts; |
| 511 | #ifdef notyet |
| 512 | uint32_t key; |
| 513 | #endif |
| 514 | uint16_t flags; |
| 515 | int hlen, isr, af; |
| 516 | |
| 517 | ifp = GRE2IFP(sc); |
| 518 | hlen = off + sizeof(struct grehdr) + 4 * sizeof(uint32_t); |
| 519 | if (m->m_pkthdr.len < hlen) |
| 520 | goto drop; |
| 521 | if (m->m_len < hlen) { |
| 522 | m = m_pullup(m, hlen); |
| 523 | if (m == NULL) |
| 524 | goto drop; |
| 525 | } |
| 526 | gh = (struct grehdr *)mtodo(m, off); |
| 527 | flags = ntohs(gh->gre_flags); |
| 528 | if (flags & ~GRE_FLAGS_MASK) |
| 529 | goto drop; |
| 530 | opts = gh->gre_opts; |
| 531 | hlen = 2 * sizeof(uint16_t); |
| 532 | if (flags & GRE_FLAGS_CP) { |
| 533 | /* reserved1 field must be zero */ |
| 534 | if (((uint16_t *)opts)[1] != 0) |
| 535 | goto drop; |
| 536 | if (in_cksum_skip(m, m->m_pkthdr.len, off) != 0) |
| 537 | goto drop; |
| 538 | hlen += 2 * sizeof(uint16_t); |
| 539 | opts++; |
| 540 | } |
| 541 | if (flags & GRE_FLAGS_KP) { |
| 542 | #ifdef notyet |
| 543 | /* |
| 544 | * XXX: The current implementation uses the key only for outgoing |
| 545 | * packets. But we can check the key value here, or even in the |
| 546 | * encapcheck function. |
| 547 | */ |
| 548 | key = ntohl(*opts); |
| 549 | #endif |
| 550 | hlen += sizeof(uint32_t); |
| 551 | opts++; |
| 552 | } |
| 553 | #ifdef notyet |
| 554 | } else |
| 555 | key = 0; |
| 556 | |
| 557 | if (sc->gre_key != 0 && (key != sc->gre_key || key != 0)) |
no test coverage detected