* Send a single message to the TCP at address specified by * the given TCP/IP header. If m == NULL, then we make a copy * of the tcpiphdr at th and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection. If flags are given then we send * a message back to the TCP which originated the segment th, * and discard the mbuf
| 1393 | * NOTE: If m != NULL, then th must point to *inside* the mbuf. |
| 1394 | */ |
| 1395 | void |
| 1396 | tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, |
| 1397 | tcp_seq ack, tcp_seq seq, int flags) |
| 1398 | { |
| 1399 | struct tcpopt to; |
| 1400 | struct inpcb *inp; |
| 1401 | struct ip *ip; |
| 1402 | struct mbuf *optm; |
| 1403 | struct tcphdr *nth; |
| 1404 | u_char *optp; |
| 1405 | #ifdef INET6 |
| 1406 | struct ip6_hdr *ip6; |
| 1407 | int isipv6; |
| 1408 | #endif /* INET6 */ |
| 1409 | int optlen, tlen, win; |
| 1410 | bool incl_opts; |
| 1411 | |
| 1412 | KASSERT(tp != NULL || m != NULL, ("tcp_respond: tp and m both NULL")); |
| 1413 | NET_EPOCH_ASSERT(); |
| 1414 | |
| 1415 | #ifdef INET6 |
| 1416 | isipv6 = ((struct ip *)ipgen)->ip_v == (IPV6_VERSION >> 4); |
| 1417 | ip6 = ipgen; |
| 1418 | #endif /* INET6 */ |
| 1419 | ip = ipgen; |
| 1420 | |
| 1421 | if (tp != NULL) { |
| 1422 | inp = tp->t_inpcb; |
| 1423 | KASSERT(inp != NULL, ("tcp control block w/o inpcb")); |
| 1424 | INP_WLOCK_ASSERT(inp); |
| 1425 | } else |
| 1426 | inp = NULL; |
| 1427 | |
| 1428 | incl_opts = false; |
| 1429 | win = 0; |
| 1430 | if (tp != NULL) { |
| 1431 | if (!(flags & TH_RST)) { |
| 1432 | win = sbspace(&inp->inp_socket->so_rcv); |
| 1433 | if (win > TCP_MAXWIN << tp->rcv_scale) |
| 1434 | win = TCP_MAXWIN << tp->rcv_scale; |
| 1435 | } |
| 1436 | if ((tp->t_flags & TF_NOOPT) == 0) |
| 1437 | incl_opts = true; |
| 1438 | } |
| 1439 | if (m == NULL) { |
| 1440 | m = m_gethdr(M_NOWAIT, MT_DATA); |
| 1441 | if (m == NULL) |
| 1442 | return; |
| 1443 | m->m_data += max_linkhdr; |
| 1444 | #ifdef INET6 |
| 1445 | if (isipv6) { |
| 1446 | bcopy((caddr_t)ip6, mtod(m, caddr_t), |
| 1447 | sizeof(struct ip6_hdr)); |
| 1448 | ip6 = mtod(m, struct ip6_hdr *); |
| 1449 | nth = (struct tcphdr *)(ip6 + 1); |
| 1450 | } else |
| 1451 | #endif /* INET6 */ |
| 1452 | { |
no test coverage detected