📄 tcp_subr.c
字号:
#ifndef lintstatic char *sccsid = "@(#)tcp_subr.c 4.1 ULTRIX 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * * * 2-Jan_90 U. Sinkewicz * Performance enhancements to uniprocessor kernel. * * 30-May-89 U. Sinkewicz * Added so->ref and SO_LOCK to fix the smp problem caused * by unlocking the socket and then locking it again to * accommodate the lock hierarchy and sleeps. Changed * call interface to ip_output() to support asymmetric * network drivers. * * 05-May-89 Michael G. Mc Menemy * Add XTI support. * * 27-Mar-89 U. Sinkewicz * Lowered ipl on lk_rtentry, lk_ifnet, lk_in_ifaddr; replaced * tcpstatictics with a macro as per lp changes made 3.16.89. * * 3-Mar-89 U. Sinkewicz * Added new directory layout to smp file. * * 15-Jan-88 lp * Merge of final 43BSD changes. * * Larry Cohen - 09/16/85 * * Add 43bsd alpha tape changes for subnet routing * * * ************************************************************************//* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * tcp_subr.c 6.6 (Berkeley) 6/8/85 */#include "../h/param.h"#include "../h/systm.h"#include "../h/smp_lock.h"#include "../h/mbuf.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/protosw.h"#include "../h/errno.h"#include "../net/net/route.h"#include "../net/net/if.h"#include "../net/netinet/in.h"#include "../net/netinet/in_pcb.h"#include "../net/netinet/in_systm.h"#include "../net/netinet/ip.h"#include "../net/netinet/ip_var.h"#include "../net/netinet/ip_icmp.h"#include "../net/netinet/tcp.h"#include "../net/netinet/tcp_fsm.h"#include "../net/netinet/tcp_seq.h"#include "../net/netinet/tcp_timer.h"#include "../net/netinet/tcp_var.h"#include "../net/netinet/tcpip.h"#ifdef XTI#include "../h/file.h"#endif XTIint tcp_ttl = TCP_TTL;/* * Tcp initialization. * SMP: Initialize the tcb smp lock and the tcpstat smp lock. */struct lock_t lk_tcb; /* SMP */struct lock_t lk_tcpstat; /* SMP */tcp_init(){ int s; s = splnet(); /* SMP */ smp_lock(&lk_tcpiss, LK_RETRY); tcp_iss = 1; /* wrong */ smp_unlock(&lk_tcpiss); splx(s); lockinit(&lk_tcb, &lock_tcb_d); lockinit(&lk_tcpstat, &lock_tcpstat_d); s = splnet(); /* SMP */ smp_lock(&lk_tcb, LK_RETRY); tcb.inp_next = tcb.inp_prev = &tcb; smp_unlock(&lk_tcb); splx(s);#ifdef XTI /* set-up XTI default characteristics */ /* stored per provider */ xti_tcpinfo.addr = sizeof(struct sockaddr_in); xti_tcpinfo.options = sizeof(struct tcp_options); xti_tcpinfo.tsdu = 0; xti_tcpinfo.etsdu = -1; xti_tcpinfo.connect = -2; xti_tcpinfo.discon = -2; xti_tcpinfo.servtype = T_COTS_ORD;#endif XTI}/* * Create template to be used to send tcp packets on a connection. * Call after host entry created, allocates an mbuf and fills * in a skeletal tcp/ip header, minimizing the amount of work * necessary when the connection is used. *//* SMP: lock held coming in. */struct tcpiphdr *tcp_template(tp) struct tcpcb *tp;{ register struct inpcb *inp = tp->t_inpcb; register struct mbuf *m; register struct tcpiphdr *n; if (smp_debug){ if (smp_owner(&inp->inp_socket->lk_socket) == 0) panic("tcp_template not lock owner"); } if((n = tp->t_template) == 0) { m = m_get(M_DONTWAIT, MT_DATA); if (m == NULL) return (0); m->m_off = MMAXOFF - sizeof (struct tcpiphdr); m->m_len = sizeof (struct tcpiphdr); n = mtod(m, struct tcpiphdr *); } n->ti_next = n->ti_prev = 0; n->ti_x1 = 0; n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); n->ti_src = inp->inp_laddr; n->ti_dst = inp->inp_faddr; n->ti_sport = inp->inp_lport; n->ti_dport = inp->inp_fport; n->ti_seq = 0; n->ti_ack = 0; n->ti_x2 = 0; n->ti_off = 5; n->ti_flags = 0; n->ti_win = 0; n->ti_sum = 0; n->ti_urp = 0; return (n);}/* * Send a single message to the TCP at address specified by * the given TCP/IP header. If flags==0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. * * Enter from tcp_input and tcp_timer. No locks set going in. *//* Need to pass down so pointer to set the locks * properly. Tp pointer is not sufficient to determine locking * because so could be locked and tp could be zero. *//* tcp_respond(tp, ti, ack, seq, flags) */tcp_respond(tp, ti, ack, seq, flags, so) struct tcpcb *tp; register struct tcpiphdr *ti; tcp_seq ack, seq; int flags; struct socket *so;{ register struct mbuf *m; int win = 0, tlen; struct route *ro = 0; /* * SMP: tp may be NULL; Check for smp * lock ownership only if tp is okay */ if (tp) { win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); ro = &tp->t_inpcb->inp_route; } if (flags == 0) { m = m_get(M_DONTWAIT, MT_DATA); if (m == NULL){ return; }#ifndef TCP_43BSD tlen = 1;#else tlen = 0;#endif m->m_len = sizeof (struct tcpiphdr) + 1; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else { m = dtom(ti); m_freem(m->m_next); m->m_next = 0; m->m_off = (int)ti - (int)m; tlen = 0; m->m_len = sizeof (struct tcpiphdr);#define xchg(a,b,type) { type t; t=a; a=b; b=t; } xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); xchg(ti->ti_dport, ti->ti_sport, u_short);#undef xchg } ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); ti->ti_x2 = 0; ti->ti_off = sizeof (struct tcphdr) >> 2; ti->ti_flags = flags; ti->ti_win = htons((u_short)win); ti->ti_urp = 0;#ifdef TCPLOOPBACK if (ti->ti_src.s_addr == ti->ti_dst.s_addr) { /* Fake IP transit and get to TCP layer fast */ ((struct ip *)ti)->ip_hl = sizeof (struct ip) >> 2; ((struct ip *)ti)->ip_len = sizeof (struct tcphdr) + tlen; if (so){ smp_unlock(&so->lk_socket); } tcp_input(m); if (so){ SO_LOCK(so); } } else {#endif TCPLOOPBACK ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; ((struct ip *)ti)->ip_ttl = tcp_ttl; (void) ip_output(m, (struct mbuf *)0, ro, 0, so);#ifdef TCPLOOPBACK }#endif TCPLOOPBACK}/* * Create a new TCP control block, making an * empty reassembly queue and hooking it to the argument * protocol control block. *//* SMP: Note that inp is locked coming in; socket is locked * coming in. */struct tcpcb *tcp_newtcpcb(inp) struct inpcb *inp;{#ifdef old struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);#endif register struct tcpcb *tp;#ifdef old if (smp_debug){ if (smp_owner(&inp->inp_socket->lk_socket) == 0) panic(" tcp_newtcpcb not lock owner"); } if (m == NULL) return ((struct tcpcb *)0); tp = mtod(m, struct tcpcb *);#endif KM_ALLOC(tp, struct tcpcb *, sizeof(struct tcpcb), KM_PCB, KM_CLEAR|KM_NOWAIT); if(tp == NULL) return((struct tcpcb *)0); tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; tp->t_maxseg = TCP_MSS; tp->t_flags = 0; /* sends options! */ tp->t_inpcb = inp; /* * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; tp->t_rttvar = TCPTV_SRTTDFLT << 2; TCPT_RANGESET(tp->t_rxtcur, ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, TCPTV_MIN, TCPTV_REXMTMAX); tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd); tp->snd_ssthresh = 65535; /* XXX */ inp->inp_ppcb = (caddr_t)tp;#ifdef XTI /* set-up default tcp options */ tp->xti_tcp_defqos.precedence = T_ROUTINE; tp->xti_tcp_defqos.timeout = (TCP_LINGERTIME*1000); tp->xti_tcp_defqos.max_seg_size = tp->t_maxseg; tp->xti_tcp_defqos.secopt.security = T_UNUSED; tp->xti_tcp_defqos.secopt.compartment = T_UNUSED; tp->xti_tcp_defqos.secopt.handling = T_UNUSED; tp->xti_tcp_defqos.secopt.tcc = T_UNUSED; /* load default options into negotiated area */ tp->xti_neg_qos = tp->xti_tcp_defqos;#endif XTI return (tp);}/* * Drop a TCP connection, reporting * the specified error. If connection is synchronized, * then send a RST to peer. */struct tcpcb *tcp_drop(tp, errno) register struct tcpcb *tp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -