From 8075bb0e1fbda1594b6a6713a2bc62f718f5f1d8 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Mon, 27 Sep 1982 02:30:41 -0800 Subject: [PATCH] first working version SCCS-vsn: sys/netinet/in_pcb.c 4.31 SCCS-vsn: sys/netinet/tcp_input.c 1.74 SCCS-vsn: sys/netinet/tcp_usrreq.c 1.62 SCCS-vsn: sys/netinet/udp_usrreq.c 4.32 --- usr/src/sys/netinet/in_pcb.c | 190 +++++++------------------------ usr/src/sys/netinet/tcp_input.c | 27 +++-- usr/src/sys/netinet/tcp_usrreq.c | 86 +++++++------- usr/src/sys/netinet/udp_usrreq.c | 34 ++++-- 4 files changed, 130 insertions(+), 207 deletions(-) diff --git a/usr/src/sys/netinet/in_pcb.c b/usr/src/sys/netinet/in_pcb.c index dcdee567cd..513ac48db2 100644 --- a/usr/src/sys/netinet/in_pcb.c +++ b/usr/src/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* in_pcb.c 4.30 82/07/24 */ +/* in_pcb.c 4.31 82/09/26 */ #include "../h/param.h" #include "../h/systm.h" @@ -14,38 +14,6 @@ #include "../net/in_pcb.h" #include "../h/protosw.h" -/* - * Routines to manage internet protocol control blocks. - * - * At PRU_ATTACH time a protocol control block is allocated in - * in_pcballoc() and inserted on a doubly-linked list of such blocks - * for the protocol. A port address is either requested (and verified - * to not be in use) or assigned at this time. We also allocate - * space in the socket sockbuf structures here, although this is - * not a clearly correct place to put this function. - * - * A connectionless protocol will have its protocol control block - * removed at PRU_DETACH time, when the socket will be freed (freeing - * the space reserved) and the block will be removed from the list of - * blocks for its protocol. - * - * A connection-based protocol may be connected to a remote peer at - * PRU_CONNECT time through the routine in_pcbconnect(). In the normal - * case a PRU_DISCONNECT occurs causing a in_pcbdisconnect(). - * It is also possible that higher-level routines will opt out of the - * relationship with the connection before the connection shut down - * is complete. This often occurs in protocols like TCP where we must - * hold on to the protocol control block for a unreasonably long time - * after the connection is used up to avoid races in later connection - * establishment. To handle this we allow higher-level routines to - * disassociate themselves from the socket, marking it SS_NOFDREF while - * the disconnect is in progress. We notice that this has happened - * when the disconnect is complete, and perform the PRU_DETACH operation, - * freeing the socket. - * - * TODO: - * use hashing - */ struct in_addr zeroin_addr; in_pcbreserve(so, sndcc, rcvcc) @@ -82,116 +50,51 @@ in_pcballoc(so, head) return (0); } -in_pcbbind(inp, sin) +in_pcbbind(inp, nam) register struct inpcb *inp; - struct sockaddr_in *sin; + struct mbuf *nam; { register struct socket *so = inp->inp_socket; register struct inpcb *head = inp->inp_head; + register struct sockaddr_in *sin; u_short lport = 0; if (ifnet == 0) return (EADDRNOTAVAIL); - if (sin) { - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); - if (sin->sin_addr.s_addr) { - int tport = sin->sin_port; + if (inp->inp_lport || inp->inp_laddr.s_addr) + return (EINVAL); + if (nam == 0) + goto noname; + sin = mtod(nam, struct sockaddr_in *); + if (nam->m_len != sizeof (*sin)) + return (EINVAL); + if (sin->sin_addr.s_addr) { + int tport = sin->sin_port; - sin->sin_port = 0; /* yech... */ - if (if_ifwithaddr((struct sockaddr *)sin) == 0) - return (EADDRNOTAVAIL); - sin->sin_port = tport; - } - lport = sin->sin_port; - if (lport) { - u_short aport = lport; - int wild = 0; -#if vax - aport = htons(aport); -#endif - /* GROSS */ - if (aport < IPPORT_RESERVED && u.u_uid != 0) - return (EACCES); - if ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || - (so->so_options & SO_ACCEPTCONN) == 0) - wild = INPLOOKUP_WILDCARD; - if (in_pcblookup(head, - zeroin_addr, 0, sin->sin_addr, lport, wild)) - return (EADDRINUSE); - } + sin->sin_port = 0; /* yech... */ + if (if_ifwithaddr((struct sockaddr *)sin) == 0) + return (EADDRNOTAVAIL); + sin->sin_port = tport; } - if (sin) - inp->inp_laddr = sin->sin_addr; - if (lport == 0) - do { - if (head->inp_lport++ < IPPORT_RESERVED) - head->inp_lport = IPPORT_RESERVED; - lport = htons(head->inp_lport); - } while (in_pcblookup(head, - zeroin_addr, 0, inp->inp_laddr, lport, 0)); - inp->inp_lport = lport; - return (0); -} - -/* BEGIN DEPRECATED */ -/* - * Allocate a protocol control block, space - * for send and receive data, and local host information. - * Return error. If no error make socket point at pcb. - */ -in_pcbattach(so, head, sndcc, rcvcc, sin) - struct socket *so; - struct inpcb *head; - int sndcc, rcvcc; - struct sockaddr_in *sin; -{ - struct mbuf *m; - register struct inpcb *inp; - u_short lport = 0; - - if (ifnet == 0) - return (EADDRNOTAVAIL); - if (sin) { - if (sin->sin_family != AF_INET) - return (EAFNOSUPPORT); - if (sin->sin_addr.s_addr) { - int tport = sin->sin_port; + lport = sin->sin_port; + if (lport) { + u_short aport = lport; + int wild = 0; - sin->sin_port = 0; /* yech... */ - if (if_ifwithaddr((struct sockaddr *)sin) == 0) - return (EADDRNOTAVAIL); - sin->sin_port = tport; - } - lport = sin->sin_port; - if (lport) { - u_short aport = lport; - int wild = 0; #if vax - aport = htons(aport); + aport = htons(aport); #endif - /* GROSS */ - if (aport < IPPORT_RESERVED && u.u_uid != 0) - return (EACCES); - if ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || - (so->so_options & SO_ACCEPTCONN) == 0) - wild = INPLOOKUP_WILDCARD; - if (in_pcblookup(head, - zeroin_addr, 0, sin->sin_addr, lport, wild)) - return (EADDRINUSE); - } + /* GROSS */ + if (aport < IPPORT_RESERVED && u.u_uid != 0) + return (EACCES); + if ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0) + wild = INPLOOKUP_WILDCARD; + if (in_pcblookup(head, + zeroin_addr, 0, sin->sin_addr, lport, wild)) + return (EADDRINUSE); } - m = m_getclr(M_DONTWAIT); - if (m == 0) - return (ENOBUFS); - if (sbreserve(&so->so_snd, sndcc) == 0) - goto bad; - if (sbreserve(&so->so_rcv, rcvcc) == 0) - goto bad2; - inp = mtod(m, struct inpcb *); - inp->inp_head = head; - if (sin) - inp->inp_laddr = sin->sin_addr; + inp->inp_laddr = sin->sin_addr; +noname: if (lport == 0) do { if (head->inp_lport++ < IPPORT_RESERVED) @@ -200,17 +103,8 @@ in_pcbattach(so, head, sndcc, rcvcc, sin) } while (in_pcblookup(head, zeroin_addr, 0, inp->inp_laddr, lport, 0)); inp->inp_lport = lport; - inp->inp_socket = so; - insque(inp, head); - so->so_pcb = (caddr_t)inp; return (0); -bad2: - sbrelease(&so->so_snd); -bad: - (void) m_free(m); - return (ENOBUFS); } -/* END DEPRECATED */ /* * Connect from a socket to a specified address. @@ -218,13 +112,16 @@ bad: * If don't have a local address for this socket yet, * then pick one. */ -in_pcbconnect(inp, sin) +in_pcbconnect(inp, nam) struct inpcb *inp; - struct sockaddr_in *sin; + struct mbuf *nam; { struct ifnet *ifp; struct sockaddr_in *ifaddr; + register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); + if (nam->m_len != sizeof (*sin)) + return (EINVAL); if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); if (sin->sin_addr.s_addr == 0 || sin->sin_port == 0) @@ -281,12 +178,14 @@ in_pcbdetach(inp) (void) m_free(dtom(inp)); } -in_setsockaddr(sin, inp) - register struct sockaddr_in *sin; +in_setsockaddr(inp, nam) register struct inpcb *inp; + struct mbuf *nam; { - if (sin == 0 || inp == 0) - panic("setsockaddr_in"); + register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); + + nam->m_len = sizeof (*sin); + sin = mtod(nam, struct sockaddr_in *); bzero((caddr_t)sin, sizeof (*sin)); sin->sin_family = AF_INET; sin->sin_port = inp->inp_lport; @@ -323,9 +222,6 @@ in_pcbnotify(head, dst, errno, abort) splx(s); } -/* - * SHOULD ALLOW MATCH ON MULTI-HOMING ONLY - */ struct inpcb * in_pcblookup(head, faddr, fport, laddr, lport, flags) struct inpcb *head; diff --git a/usr/src/sys/netinet/tcp_input.c b/usr/src/sys/netinet/tcp_input.c index 4e4b2ff8e5..b173e14448 100644 --- a/usr/src/sys/netinet/tcp_input.c +++ b/usr/src/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* tcp_input.c 1.73 82/07/24 */ +/* tcp_input.c 1.74 82/09/26 */ #include "../h/param.h" #include "../h/systm.h" @@ -24,7 +24,7 @@ int tcpprintfs = 0; int tcpcksum = 1; -struct sockaddr_in tcp_in = { AF_INET }; +struct mbuf tcp_mb; struct tcpiphdr tcp_saveti; extern tcpnodelack; @@ -133,8 +133,7 @@ tcp_input(m0) #endif /* - * Locate pcb for segment. On match, update the local - * address stored in the block to reflect anchoring. + * Locate pcb for segment. */ inp = in_pcblookup (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport, @@ -202,22 +201,33 @@ tcp_input(m0) * Enter SYN_RECEIVED state, and process any other fields of this * segment in this state. */ - case TCPS_LISTEN: + case TCPS_LISTEN: { + struct mbuf *m = m_get(M_DONTWAIT); + register struct sockaddr_in *sin; + + if (m == 0) + goto drop; + m->m_off = MMINOFF; + m->m_len = sizeof (struct sockaddr_in); if (tiflags & TH_RST) goto drop; if (tiflags & TH_ACK) goto dropwithreset; if ((tiflags & TH_SYN) == 0) goto drop; - tcp_in.sin_addr = ti->ti_src; - tcp_in.sin_port = ti->ti_sport; + sin = mtod(m, struct sockaddr_in *); + sin->sin_family = AF_INET; + sin->sin_addr = ti->ti_src; + sin->sin_port = ti->ti_sport; laddr = inp->inp_laddr; if (inp->inp_laddr.s_addr == 0) inp->inp_laddr = ti->ti_dst; - if (in_pcbconnect(inp, (struct sockaddr_in *)&tcp_in)) { + if (in_pcbconnect(inp, m)) { inp->inp_laddr = laddr; + m_free(m); goto drop; } + m_free(m); tp->t_template = tcp_template(tp); if (tp->t_template == 0) { in_pcbdisconnect(inp); @@ -232,6 +242,7 @@ tcp_input(m0) tp->t_state = TCPS_SYN_RECEIVED; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP; goto trimthenstep6; + } /* * If the state is SYN_SENT: diff --git a/usr/src/sys/netinet/tcp_usrreq.c b/usr/src/sys/netinet/tcp_usrreq.c index 02a468d2dd..37e8541501 100644 --- a/usr/src/sys/netinet/tcp_usrreq.c +++ b/usr/src/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* tcp_usrreq.c 1.61 82/07/24 */ +/* tcp_usrreq.c 1.62 82/09/26 */ #include "../h/param.h" #include "../h/systm.h" @@ -33,11 +33,11 @@ struct tcpcb *tcp_newtcpcb(); * then m is the mbuf chain of send data. If this is a timer expiration * (called from the software clock routine), then timertype tells which timer. */ -tcp_usrreq(so, req, m, addr) +tcp_usrreq(so, req, m, nam, opt) struct socket *so; int req; - struct mbuf *m; - caddr_t addr; + struct mbuf *m, *nam; + struct socketopt *opt; { register struct inpcb *inp = sotoinpcb(so); register struct tcpcb *tp; @@ -49,16 +49,6 @@ tcp_usrreq(so, req, m, addr) * When a TCP is attached to a socket, then there will be * a (struct inpcb) pointed at by the socket, and this * structure will point at a subsidary (struct tcpcb). - * The normal sequence of events is: - * PRU_ATTACH creating these structures - * PRU_CONNECT connecting to a remote peer - * (PRU_SEND|PRU_RCVD)* exchanging data - * PRU_DISCONNECT disconnecting from remote peer - * PRU_DETACH deleting the structures - * With the operations from PRU_CONNECT through PRU_DISCONNECT - * possible repeated several times. - * - * MULTIPLE CONNECTS ARE NOT YET IMPLEMENTED. */ if (inp == 0 && req != PRU_ATTACH) { splx(s); @@ -66,6 +56,7 @@ tcp_usrreq(so, req, m, addr) } if (inp) { tp = intotcpcb(inp); + /* WHAT IF TP IS 0? */ #ifdef KPROF tcp_acounts[tp->t_state][req]++; #endif @@ -76,16 +67,14 @@ tcp_usrreq(so, req, m, addr) /* * TCP attaches to socket via PRU_ATTACH, reserving space, - * and internet and TCP control blocks. - * If the socket is to receive connections, - * then the LISTEN state is entered. + * and an internet control block. */ case PRU_ATTACH: if (inp) { error = EISCONN; break; } - error = tcp_attach(so, (struct sockaddr *)addr); + error = tcp_attach(so, nam); if (error) break; if ((so->so_options & SO_DONTLINGER) == 0) @@ -109,6 +98,25 @@ tcp_usrreq(so, req, m, addr) } break; + /* + * Give the socket an address. + */ + case PRU_BIND: + error = in_pcbbind(inp, nam); + if (error) + break; + break; + + /* + * Prepare to accept connections. + */ + case PRU_LISTEN: + if (inp->inp_lport == 0) + error = in_pcbbind(inp, (struct mbuf *)0); + if (error == 0) + tp->t_state = TCPS_LISTEN; + break; + /* * Initiate connection to peer. * Create a template for use in transmissions on this connection. @@ -117,7 +125,12 @@ tcp_usrreq(so, req, m, addr) * Send initial segment on connection. */ case PRU_CONNECT: - error = in_pcbconnect(inp, (struct sockaddr_in *)addr); + if (inp->inp_lport == 0) { + error = in_pcbbind(inp, (struct mbuf *)0); + if (error) + break; + } + error = in_pcbconnect(inp, nam); if (error) break; tp->t_template = tcp_template(tp); @@ -155,16 +168,14 @@ tcp_usrreq(so, req, m, addr) * of the peer, storing through addr. */ case PRU_ACCEPT: { - struct sockaddr_in *sin = (struct sockaddr_in *)addr; + struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); - if (sin) { - bzero((caddr_t)sin, sizeof (*sin)); - sin->sin_family = AF_INET; - sin->sin_port = inp->inp_fport; - sin->sin_addr = inp->inp_faddr; - } - } + nam->m_len = sizeof (struct sockaddr_in); + sin->sin_family = AF_INET; + sin->sin_port = inp->inp_fport; + sin->sin_addr = inp->inp_faddr; break; + } /* * Mark the connection as being incapable of further output. @@ -253,7 +264,7 @@ tcp_usrreq(so, req, m, addr) break; case PRU_SOCKADDR: - in_setsockaddr((struct sockaddr_in *)addr, inp); + in_setsockaddr(inp, nam); break; /* @@ -261,8 +272,8 @@ tcp_usrreq(so, req, m, addr) * routine for tracing's sake. */ case PRU_SLOWTIMO: - tcp_timers(tp, (int)addr); - req |= (int)addr << 8; /* for debug's sake */ + tcp_timers(tp, (int)nam); + req |= (int)nam << 8; /* for debug's sake */ break; default: @@ -281,9 +292,8 @@ int tcp_recvspace = 1024*2; * internet protocol control block, tcp control block, * bufer space, and entering LISTEN state if to accept connections. */ -tcp_attach(so, sa) +tcp_attach(so) struct socket *so; - struct sockaddr *sa; { register struct tcpcb *tp; struct inpcb *inp; @@ -294,20 +304,14 @@ tcp_attach(so, sa) goto bad; error = in_pcballoc(so, &tcb); if (error) - goto bad2; - inp = (struct inpcb *)so->so_pcb; - if (sa || ((so->so_options & SO_ACCEPTCONN) == 0 && so->so_head == 0)) { - error = in_pcbbind(inp, sa); - if (error) - goto bad2; - } + goto bad; + inp = sotoinpcb(so); tp = tcp_newtcpcb(inp); if (tp == 0) { error = ENOBUFS; goto bad2; } - tp->t_state = - (so->so_options & SO_ACCEPTCONN) ? TCPS_LISTEN : TCPS_CLOSED; + tp->t_state = TCPS_CLOSED; return (0); bad2: in_pcbdetach(inp); diff --git a/usr/src/sys/netinet/udp_usrreq.c b/usr/src/sys/netinet/udp_usrreq.c index 3a2893a528..6c2e535c8f 100644 --- a/usr/src/sys/netinet/udp_usrreq.c +++ b/usr/src/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* udp_usrreq.c 4.31 82/08/15 */ +/* udp_usrreq.c 4.32 82/09/26 */ #include "../h/param.h" #include "../h/dir.h" @@ -204,11 +204,11 @@ udp_output(inp, m0) so->so_state & SS_PRIV)); } -udp_usrreq(so, req, m, addr) +udp_usrreq(so, req, m, nam, opt) struct socket *so; int req; - struct mbuf *m; - caddr_t addr; + struct mbuf *m, *nam; + struct socketopt *opt; { struct inpcb *inp = sotoinpcb(so); int error = 0; @@ -220,8 +220,12 @@ udp_usrreq(so, req, m, addr) case PRU_ATTACH: if (inp != 0) return (EINVAL); - error = in_pcbattach(so, &udb, 2048, 2048, - (struct sockaddr_in *)addr); + error = in_pcballoc(so, &udb); + if (error) + break; + error = in_pcbreserve(so, 2048, 2048); + if (error) + break; break; case PRU_DETACH: @@ -230,10 +234,18 @@ udp_usrreq(so, req, m, addr) in_pcbdetach(inp); break; + case PRU_BIND: + error = in_pcbbind(inp, nam); + break; + + case PRU_LISTEN: + error = EOPNOTSUPP; + break; + case PRU_CONNECT: if (inp->inp_faddr.s_addr) return (EISCONN); - error = in_pcbconnect(inp, (struct sockaddr_in *)addr); + error = in_pcbconnect(inp, nam); if (error == 0) soisconnected(so); break; @@ -255,11 +267,11 @@ udp_usrreq(so, req, m, addr) case PRU_SEND: { struct in_addr laddr; - if (addr) { + if (nam) { laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr) return (EISCONN); - error = in_pcbconnect(inp, (struct sockaddr_in *)addr); + error = in_pcbconnect(inp, nam); if (error) break; } else { @@ -267,7 +279,7 @@ udp_usrreq(so, req, m, addr) return (ENOTCONN); } error = udp_output(inp, m); - if (addr) { + if (nam) { in_pcbdisconnect(inp); inp->inp_laddr = laddr; } @@ -284,7 +296,7 @@ udp_usrreq(so, req, m, addr) return (EOPNOTSUPP); case PRU_SOCKADDR: - in_setsockaddr((struct sockaddr_in *)addr, inp); + in_setsockaddr(inp, nam); break; default: -- 2.20.1