* Handle an incoming packet. The packet includes the IP header. */
| 742 | * Handle an incoming packet. The packet includes the IP header. |
| 743 | */ |
| 744 | static int |
| 745 | ng_pptpgre_rcvdata_lower(hook_p hook, item_p item) |
| 746 | { |
| 747 | hpriv_p hpriv; |
| 748 | node_p node = NG_HOOK_NODE(hook); |
| 749 | const priv_p priv = NG_NODE_PRIVATE(node); |
| 750 | int iphlen, grelen, extralen; |
| 751 | const struct greheader *gre; |
| 752 | const struct ip *ip; |
| 753 | int error = 0; |
| 754 | struct mbuf *m; |
| 755 | |
| 756 | roqh sendq = SLIST_HEAD_INITIALIZER(sendq); /* send queue on stack */ |
| 757 | struct ng_pptpgre_roq *last = NULL; /* last packet in the sendq */ |
| 758 | struct ng_pptpgre_roq *np, *prev; |
| 759 | struct ng_pptpgre_roq temp = { { NULL }, NULL, 0 }; |
| 760 | long diff; |
| 761 | u_int32_t seq; |
| 762 | |
| 763 | m = NGI_M(item); |
| 764 | /* Update stats */ |
| 765 | priv->stats.recvPackets++; |
| 766 | priv->stats.recvOctets += m->m_pkthdr.len; |
| 767 | |
| 768 | /* Sanity check packet length */ |
| 769 | if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) { |
| 770 | priv->stats.recvRunts++; |
| 771 | ERROUT(EINVAL); |
| 772 | } |
| 773 | |
| 774 | /* Safely pull up the complete IP+GRE headers */ |
| 775 | if (m->m_len < sizeof(*ip) + sizeof(*gre)) { |
| 776 | if ((m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) { |
| 777 | priv->stats.memoryFailures++; |
| 778 | _NGI_M(item) = NULL; |
| 779 | ERROUT(ENOBUFS); |
| 780 | } |
| 781 | _NGI_M(item) = m; |
| 782 | } |
| 783 | ip = mtod(m, const struct ip *); |
| 784 | iphlen = ip->ip_hl << 2; |
| 785 | if (m->m_len < iphlen + sizeof(*gre)) { |
| 786 | if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) { |
| 787 | priv->stats.memoryFailures++; |
| 788 | _NGI_M(item) = NULL; |
| 789 | ERROUT(ENOBUFS); |
| 790 | } |
| 791 | _NGI_M(item) = m; |
| 792 | ip = mtod(m, const struct ip *); |
| 793 | } |
| 794 | gre = (const struct greheader *)((const u_char *)ip + iphlen); |
| 795 | grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck); |
| 796 | if (m->m_pkthdr.len < iphlen + grelen) { |
| 797 | priv->stats.recvRunts++; |
| 798 | ERROUT(EINVAL); |
| 799 | } |
| 800 | if (m->m_len < iphlen + grelen) { |
| 801 | if ((m = m_pullup(m, iphlen + grelen)) == NULL) { |
nothing calls this directly
no test coverage detected