* Handle an incoming multi-link fragment * * The fragment reassembly algorithm is somewhat complex. This is mainly * because we are required not to reorder the reconstructed packets, yet * fragments are only guaranteed to arrive in order on a per-link basis. * In other words, when we have a complete packet ready, but the previous * packet is still incomplete, we have to decide between delive
| 1519 | * This assumes linkNum != NG_PPP_BUNDLE_LINKNUM. |
| 1520 | */ |
| 1521 | static int |
| 1522 | ng_ppp_mp_recv(node_p node, item_p item, uint16_t proto, uint16_t linkNum) |
| 1523 | { |
| 1524 | const priv_p priv = NG_NODE_PRIVATE(node); |
| 1525 | struct ng_ppp_link *const link = &priv->links[linkNum]; |
| 1526 | struct ng_ppp_frag *frag; |
| 1527 | struct ng_ppp_frag *qent; |
| 1528 | int i, diff, inserted; |
| 1529 | struct mbuf *m; |
| 1530 | int error = 0; |
| 1531 | |
| 1532 | if ((!priv->conf.enableMultilink) || proto != PROT_MP) { |
| 1533 | /* Stats */ |
| 1534 | priv->bundleStats.recvFrames++; |
| 1535 | priv->bundleStats.recvOctets += NGI_M(item)->m_pkthdr.len; |
| 1536 | |
| 1537 | mtx_unlock(&priv->rmtx); |
| 1538 | return (ng_ppp_crypt_recv(node, item, proto, linkNum)); |
| 1539 | } |
| 1540 | |
| 1541 | NGI_GET_M(item, m); |
| 1542 | |
| 1543 | /* Get a new frag struct from the free queue */ |
| 1544 | if ((frag = TAILQ_FIRST(&priv->fragsfree)) == NULL) { |
| 1545 | printf("No free fragments headers in ng_ppp!\n"); |
| 1546 | NG_FREE_M(m); |
| 1547 | goto process; |
| 1548 | } |
| 1549 | |
| 1550 | /* Extract fragment information from MP header */ |
| 1551 | if (priv->conf.recvShortSeq) { |
| 1552 | uint16_t shdr; |
| 1553 | |
| 1554 | if (m->m_pkthdr.len < 2) { |
| 1555 | link->stats.runts++; |
| 1556 | NG_FREE_M(m); |
| 1557 | ERROUT(EINVAL); |
| 1558 | } |
| 1559 | if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) |
| 1560 | ERROUT(ENOBUFS); |
| 1561 | |
| 1562 | shdr = be16dec(mtod(m, void *)); |
| 1563 | frag->seq = MP_SHORT_EXTEND(shdr); |
| 1564 | frag->first = (shdr & MP_SHORT_FIRST_FLAG) != 0; |
| 1565 | frag->last = (shdr & MP_SHORT_LAST_FLAG) != 0; |
| 1566 | diff = MP_SHORT_SEQ_DIFF(frag->seq, priv->mseq); |
| 1567 | m_adj(m, 2); |
| 1568 | } else { |
| 1569 | uint32_t lhdr; |
| 1570 | |
| 1571 | if (m->m_pkthdr.len < 4) { |
| 1572 | link->stats.runts++; |
| 1573 | NG_FREE_M(m); |
| 1574 | ERROUT(EINVAL); |
| 1575 | } |
| 1576 | if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) |
| 1577 | ERROUT(ENOBUFS); |
| 1578 |
no test coverage detected