| 488 | |
| 489 | #ifdef INET |
| 490 | static void |
| 491 | ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx, |
| 492 | int needport) |
| 493 | { |
| 494 | uint8_t nxt; |
| 495 | int off; |
| 496 | |
| 497 | /* Sanity check. */ |
| 498 | IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip), |
| 499 | ("packet too short")); |
| 500 | |
| 501 | if (m->m_len >= sizeof (struct ip)) { |
| 502 | const struct ip *ip = mtod(m, const struct ip *); |
| 503 | if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) |
| 504 | goto done; |
| 505 | off = ip->ip_hl << 2; |
| 506 | nxt = ip->ip_p; |
| 507 | } else { |
| 508 | struct ip ih; |
| 509 | |
| 510 | m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih); |
| 511 | if (ih.ip_off & htons(IP_MF | IP_OFFMASK)) |
| 512 | goto done; |
| 513 | off = ih.ip_hl << 2; |
| 514 | nxt = ih.ip_p; |
| 515 | } |
| 516 | |
| 517 | while (off < m->m_pkthdr.len) { |
| 518 | struct ip6_ext ip6e; |
| 519 | struct tcphdr th; |
| 520 | struct udphdr uh; |
| 521 | |
| 522 | switch (nxt) { |
| 523 | case IPPROTO_TCP: |
| 524 | spidx->ul_proto = nxt; |
| 525 | if (!needport) |
| 526 | goto done_proto; |
| 527 | if (off + sizeof(struct tcphdr) > m->m_pkthdr.len) |
| 528 | goto done; |
| 529 | m_copydata(m, off, sizeof (th), (caddr_t) &th); |
| 530 | spidx->src.sin.sin_port = th.th_sport; |
| 531 | spidx->dst.sin.sin_port = th.th_dport; |
| 532 | return; |
| 533 | case IPPROTO_UDP: |
| 534 | spidx->ul_proto = nxt; |
| 535 | if (!needport) |
| 536 | goto done_proto; |
| 537 | if (off + sizeof(struct udphdr) > m->m_pkthdr.len) |
| 538 | goto done; |
| 539 | m_copydata(m, off, sizeof (uh), (caddr_t) &uh); |
| 540 | spidx->src.sin.sin_port = uh.uh_sport; |
| 541 | spidx->dst.sin.sin_port = uh.uh_dport; |
| 542 | return; |
| 543 | case IPPROTO_AH: |
| 544 | if (off + sizeof(ip6e) > m->m_pkthdr.len) |
| 545 | goto done; |
| 546 | /* XXX Sigh, this works but is totally bogus. */ |
| 547 | m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e); |
no test coverage detected