| 110 | } |
| 111 | |
| 112 | static int |
| 113 | send_output(struct mbuf *m, struct ifnet *ifp, int direction) |
| 114 | { |
| 115 | struct ip6_hdr *ip6; |
| 116 | struct sockaddr_in6 dst; |
| 117 | struct icmp6_hdr *icmp6; |
| 118 | int icmp6len; |
| 119 | |
| 120 | /* |
| 121 | * Receive incoming (SeND-protected) or outgoing traffic |
| 122 | * (SeND-validated) from the SeND user space application. |
| 123 | */ |
| 124 | |
| 125 | switch (direction) { |
| 126 | case SND_IN: |
| 127 | if (m->m_len < (sizeof(struct ip6_hdr) + |
| 128 | sizeof(struct icmp6_hdr))) { |
| 129 | m = m_pullup(m, sizeof(struct ip6_hdr) + |
| 130 | sizeof(struct icmp6_hdr)); |
| 131 | if (!m) |
| 132 | return (ENOBUFS); |
| 133 | } |
| 134 | |
| 135 | /* Before passing off the mbuf record the proper interface. */ |
| 136 | m->m_pkthdr.rcvif = ifp; |
| 137 | |
| 138 | if (m->m_flags & M_PKTHDR) |
| 139 | icmp6len = m->m_pkthdr.len - sizeof(struct ip6_hdr); |
| 140 | else |
| 141 | panic("Doh! not the first mbuf."); |
| 142 | |
| 143 | ip6 = mtod(m, struct ip6_hdr *); |
| 144 | icmp6 = (struct icmp6_hdr *)(ip6 + 1); |
| 145 | |
| 146 | /* |
| 147 | * Output the packet as icmp6.c:icpm6_input() would do. |
| 148 | * The mbuf is always consumed, so we do not have to |
| 149 | * care about that. |
| 150 | */ |
| 151 | switch (icmp6->icmp6_type) { |
| 152 | case ND_NEIGHBOR_SOLICIT: |
| 153 | nd6_ns_input(m, sizeof(struct ip6_hdr), icmp6len); |
| 154 | break; |
| 155 | case ND_NEIGHBOR_ADVERT: |
| 156 | nd6_na_input(m, sizeof(struct ip6_hdr), icmp6len); |
| 157 | break; |
| 158 | case ND_REDIRECT: |
| 159 | icmp6_redirect_input(m, sizeof(struct ip6_hdr)); |
| 160 | break; |
| 161 | case ND_ROUTER_SOLICIT: |
| 162 | nd6_rs_input(m, sizeof(struct ip6_hdr), icmp6len); |
| 163 | break; |
| 164 | case ND_ROUTER_ADVERT: |
| 165 | nd6_ra_input(m, sizeof(struct ip6_hdr), icmp6len); |
| 166 | break; |
| 167 | default: |
| 168 | m_freem(m); |
| 169 | return (ENOSYS); |
no test coverage detected