| 208 | } |
| 209 | |
| 210 | int |
| 211 | udp6_input(struct mbuf **mp, int *offp, int proto) |
| 212 | { |
| 213 | struct mbuf *m = *mp; |
| 214 | struct ifnet *ifp; |
| 215 | struct ip6_hdr *ip6; |
| 216 | struct udphdr *uh; |
| 217 | struct inpcb *inp; |
| 218 | struct inpcbinfo *pcbinfo; |
| 219 | struct udpcb *up; |
| 220 | int off = *offp; |
| 221 | int cscov_partial; |
| 222 | int plen, ulen; |
| 223 | struct sockaddr_in6 fromsa[2]; |
| 224 | struct m_tag *fwd_tag; |
| 225 | uint16_t uh_sum; |
| 226 | uint8_t nxt; |
| 227 | |
| 228 | NET_EPOCH_ASSERT(); |
| 229 | |
| 230 | ifp = m->m_pkthdr.rcvif; |
| 231 | |
| 232 | if (m->m_len < off + sizeof(struct udphdr)) { |
| 233 | m = m_pullup(m, off + sizeof(struct udphdr)); |
| 234 | if (m == NULL) { |
| 235 | IP6STAT_INC(ip6s_exthdrtoolong); |
| 236 | *mp = NULL; |
| 237 | return (IPPROTO_DONE); |
| 238 | } |
| 239 | } |
| 240 | ip6 = mtod(m, struct ip6_hdr *); |
| 241 | uh = (struct udphdr *)((caddr_t)ip6 + off); |
| 242 | |
| 243 | UDPSTAT_INC(udps_ipackets); |
| 244 | |
| 245 | /* |
| 246 | * Destination port of 0 is illegal, based on RFC768. |
| 247 | */ |
| 248 | if (uh->uh_dport == 0) |
| 249 | goto badunlocked; |
| 250 | |
| 251 | plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6); |
| 252 | ulen = ntohs((u_short)uh->uh_ulen); |
| 253 | |
| 254 | nxt = proto; |
| 255 | cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0; |
| 256 | if (nxt == IPPROTO_UDPLITE) { |
| 257 | /* Zero means checksum over the complete packet. */ |
| 258 | if (ulen == 0) |
| 259 | ulen = plen; |
| 260 | if (ulen == plen) |
| 261 | cscov_partial = 0; |
| 262 | if ((ulen < sizeof(struct udphdr)) || (ulen > plen)) { |
| 263 | /* XXX: What is the right UDPLite MIB counter? */ |
| 264 | goto badunlocked; |
| 265 | } |
| 266 | if (uh->uh_sum == 0) { |
| 267 | /* XXX: What is the right UDPLite MIB counter? */ |
nothing calls this directly
no test coverage detected