* Insert IP options into preformed packet. Adjust IP destination as * required for IP source routing, as indicated by a non-zero in_addr at the * start of the options. * * XXX This routine assumes that the packet has no options in place. */
| 504 | * XXX This routine assumes that the packet has no options in place. |
| 505 | */ |
| 506 | struct mbuf * |
| 507 | ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen) |
| 508 | { |
| 509 | struct ipoption *p = mtod(opt, struct ipoption *); |
| 510 | struct mbuf *n; |
| 511 | struct ip *ip = mtod(m, struct ip *); |
| 512 | unsigned optlen; |
| 513 | |
| 514 | optlen = opt->m_len - sizeof(p->ipopt_dst); |
| 515 | if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET) { |
| 516 | *phlen = 0; |
| 517 | return (m); /* XXX should fail */ |
| 518 | } |
| 519 | if (p->ipopt_dst.s_addr) |
| 520 | ip->ip_dst = p->ipopt_dst; |
| 521 | if (!M_WRITABLE(m) || M_LEADINGSPACE(m) < optlen) { |
| 522 | n = m_gethdr(M_NOWAIT, MT_DATA); |
| 523 | if (n == NULL) { |
| 524 | *phlen = 0; |
| 525 | return (m); |
| 526 | } |
| 527 | m_move_pkthdr(n, m); |
| 528 | n->m_pkthdr.rcvif = NULL; |
| 529 | n->m_pkthdr.len += optlen; |
| 530 | m->m_len -= sizeof(struct ip); |
| 531 | m->m_data += sizeof(struct ip); |
| 532 | n->m_next = m; |
| 533 | m = n; |
| 534 | m->m_len = optlen + sizeof(struct ip); |
| 535 | m->m_data += max_linkhdr; |
| 536 | bcopy(ip, mtod(m, void *), sizeof(struct ip)); |
| 537 | } else { |
| 538 | m->m_data -= optlen; |
| 539 | m->m_len += optlen; |
| 540 | m->m_pkthdr.len += optlen; |
| 541 | bcopy(ip, mtod(m, void *), sizeof(struct ip)); |
| 542 | } |
| 543 | ip = mtod(m, struct ip *); |
| 544 | bcopy(p->ipopt_list, ip + 1, optlen); |
| 545 | *phlen = sizeof(struct ip) + optlen; |
| 546 | ip->ip_v = IPVERSION; |
| 547 | ip->ip_hl = *phlen >> 2; |
| 548 | ip->ip_len = htons(ntohs(ip->ip_len) + optlen); |
| 549 | return (m); |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 | * Copy options from ip to jp, omitting those not copied during |
no test coverage detected