| 390 | } |
| 391 | |
| 392 | int |
| 393 | udp_input(struct mbuf **mp, int *offp, int proto) |
| 394 | { |
| 395 | struct ip *ip; |
| 396 | struct udphdr *uh; |
| 397 | struct ifnet *ifp; |
| 398 | struct inpcb *inp; |
| 399 | uint16_t len, ip_len; |
| 400 | struct inpcbinfo *pcbinfo; |
| 401 | struct ip save_ip; |
| 402 | struct sockaddr_in udp_in[2]; |
| 403 | struct mbuf *m; |
| 404 | struct m_tag *fwd_tag; |
| 405 | int cscov_partial, iphlen; |
| 406 | |
| 407 | m = *mp; |
| 408 | iphlen = *offp; |
| 409 | ifp = m->m_pkthdr.rcvif; |
| 410 | *mp = NULL; |
| 411 | UDPSTAT_INC(udps_ipackets); |
| 412 | |
| 413 | /* |
| 414 | * Strip IP options, if any; should skip this, make available to |
| 415 | * user, and use on returned packets, but we don't yet have a way to |
| 416 | * check the checksum with options still present. |
| 417 | */ |
| 418 | if (iphlen > sizeof (struct ip)) { |
| 419 | ip_stripoptions(m); |
| 420 | iphlen = sizeof(struct ip); |
| 421 | } |
| 422 | |
| 423 | /* |
| 424 | * Get IP and UDP header together in first mbuf. |
| 425 | */ |
| 426 | if (m->m_len < iphlen + sizeof(struct udphdr)) { |
| 427 | if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) { |
| 428 | UDPSTAT_INC(udps_hdrops); |
| 429 | return (IPPROTO_DONE); |
| 430 | } |
| 431 | } |
| 432 | ip = mtod(m, struct ip *); |
| 433 | uh = (struct udphdr *)((caddr_t)ip + iphlen); |
| 434 | cscov_partial = (proto == IPPROTO_UDPLITE) ? 1 : 0; |
| 435 | |
| 436 | /* |
| 437 | * Destination port of 0 is illegal, based on RFC768. |
| 438 | */ |
| 439 | if (uh->uh_dport == 0) |
| 440 | goto badunlocked; |
| 441 | |
| 442 | /* |
| 443 | * Construct sockaddr format source address. Stuff source address |
| 444 | * and datagram in user buffer. |
| 445 | */ |
| 446 | bzero(&udp_in[0], sizeof(struct sockaddr_in) * 2); |
| 447 | udp_in[0].sin_len = sizeof(struct sockaddr_in); |
| 448 | udp_in[0].sin_family = AF_INET; |
| 449 | udp_in[0].sin_port = uh->uh_sport; |
nothing calls this directly
no test coverage detected