`
`Socket Layer
`
`Chapter 15
`
`152--164
`
`7--1 79
`
`It is common for asynchronous events to change the state of a socket. The protocol
`processing layer notifies the socket layer of the change by setting so_error and wak-
`ing any process waiting on the socket. Because of this, the socket layer must always
`examine so_error after waking to see if an error occurred while the process was
`sleeping.
`Associate socket with descriptor
`falloc allocates a descriptor for the new connection; the socket is removed from
`the accept queue by soq~eraque and attached to the £± le structure. Exercise 15.4 dis-
`cusses the call to pan±c.
`Protocol processing
`accept allocates a new mbuf to hold the foreign address and calls soaccept to do
`protocol processing. The allocation and queueing of new sockets created during con-
`nection processing is described in Section 15.12. If the process provided a buffer to
`receive the foreign address, copyout copies the address from nam and the length from
`namelen to the process. If necessary, copyout silently truncates the name to fit in the
`process’s buffer. Finally, the mbuf is released, protocol processing enabled, and accept
`returns.
`Because only one mbuf is allocated for the foreign address, transport addresses
`must fit in one mbuf. Unix domain addresses, which are pathnames in the filesystem
`(up to 1023 bytes in length), may encounter this limit, but there is no problem with the
`16-byte sockadd~_in structure for the Internet domain. The comment on line 170
`indicates that this limitation could be removed by allocating and copying an mbuf
`chain.
`
`soaccept Function
`
`soaccept, shown in Figure 15.27, calls the protocol layer to retrieve the client’s address
`for the new connection.
`
`184 soaccept(so, nam)
`185 struct socket *so;
`186 struct mbuf *nam;
`187 {
`188
`189
`
`int
`int
`
`s = splnet();
`error;
`
`uipc_socket.c
`
`190
`191
`192
`193
`194
`195
`196
`197
`
`if ((so->so_state & SS_NOFDREF) :: 0)
`panic("soaccept: [NOFDREF");
`so->so_state &= -SS_NOFDREF;
`error = (*so->so_proto->pr_usrreq) (so, PRU_ACCEPT,
`(struct mbuf *) 0, nam,
`(struct mbuf *) 0);
`
`splx(s);
`return (error);
`
`Figure 15.27 soaccept function.
`
`uipc_socket.c
`
`WISTRON CORP. EXHIBIT 1013.486
`
`
`
`Section 15.12
`
`sonewconn and soisconnected Functions 461
`
`!84-197
`
`soaccept ensures that the socket is associated with a descriptor and issues the
`PRU_ACCEPT request to the protocol. After pr_usrreq returns, ham contains the name
`of the foreign socket.
`15.12 sonewconn and soisconnected Functions
`
`In Figure 15.26 we saw that accept waits for the protocol layer to process incoming
`connection requests and to make them available through so_q. Figure 15.28 uses TCP
`to illustrate this process.
`
`accept
`
`accept
`
`wait for incomi_ng_ connection request
`
`socket{}
`
`so qO_ ;
`
`socket{}
`
`.: ~onnecdon iI
`
`socket { }
`
`complete
`connection
`
`incoming TCP SYN
`
`send SYN and ACK
`wait forA~K ..... t-
`~
`final ACK of
`TCP handshake
`
`Figure 15.28 Incoming TCP connection processing.
`
`In the upper left corner of Figure 15.28, accept calls tsleep to wait for incoming
`connections. In the lower left, tcp_input processes an incoming TCP SYN by calling
`sonewconn to create a socket for the new connection (Figure 28.7). sonewconn queues
`the socket on so_q0, since the three-way handshake is not yet complete.
`
`WISTRON CORP. EXHIBIT 1013.487
`
`
`
`462
`
`Socket Layer
`
`Chapter 15 .....
`
`Se{
`
`13
`
`13
`
`14
`
`14
`
`15
`
`When the final ACK of the TCP handshake arrives, tcp_±nput calls
`so±seonnected (Figure 29.2), which updates the new socket, moves it from so_q0 to
`so_q, and wakes up any processes that had called accept to wait for incoming con-
`nections.
`The upper right comer of the figure shows the functions we described with Fig-
`ure 15.26. When tsleep returns, accept takes the connection off so_q and issues the
`PRU_ATTACH request. The socket is associated with a new file descriptor and returned
`to the calling process.
`Figure 15.29 shows the sonewconn function.
`
`u ipc_socket 2 .c
`
`123 struct socket *
`124 sonewconn(head, connstatus)
`125 struct socket *head;
`connstatus;
`126 int
`127 {
`128
`129
`
`struct socket *so;
`int soqueue = connstatus ? 1 : 0;
`
`if (head->so_qlen + head->so_q01en > 3 * head->so_qlimit / 2)
`return ((struct socket *) 0);
`MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT) ;
`if (so == NULL)
`return ((struct socket *) 0);
`bzero((caddr_t) so, sizeof(*so));
`so->so_type = head->so_type;
`so->so_options = head->so_options & ~SO_ACCEPTCONN;
`so->so_linger = head->so_linger;
`so->so_state = head->so_state I SS_NOFDREF;
`so->so~roto = head->so_proto;
`so->so_timeo = head->so_timeo;
`so->so~gid = head->so~gid;
`(void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
`soqinsque(head, so, soqueue);
`if ((*so->so~roto->pr_usrreq) (so, PRU_ATTACH,
`(struct mbuf *) 0, (struct mbuf *) 0,
`(void} soqremque(so, soqueue);
`(void} free((caddr_t) so, M_SOCKET);
`return ((struct socket *) 0);
`
`(struct mbuf *) 0)) {
`
`}i
`
`f (connstatus) {
`sorwakeup(head);
`wakeup((caddr_t) & head->so_timeo);
`so->so_state I= connstatus;
`
`}r
`
`eturn (so);
`
`Figure 15.29 soneweonn function.
`
`uipc_socket2.c
`
`130
`131
`132
`133
`134
`135
`136
`137
`138
`139
`140
`141
`142
`143
`144
`145
`146
`147
`148
`149
`150
`151
`152
`153
`154
`155
`156
`157 }
`
`123-129
`
`The protocol layer passes head, a pointer to the socket that is accepting the incom-
`ing connection, and connstatus, a flag to indicate the state of the new connection. For
`TCP, connstatus is always 0.
`
`WISTRON CORP. EXHIBIT 1013.488
`
`
`
`sonewconn and soisconnected Functions 463
`
`130--131
`
`132--143
`
`144
`
`145--150
`
`151--157
`
`78--87
`
`so_qlen+ so_q01en >
`
`For TP4, connstatus is always SS_ISCONFIRMING. The connection is implicitly confirmed
`when a process begins reading from or writing to the socket.
`Limit incoming connections
`son~wconn prohibits additional connections when the following inequality is true:
`3 x so_qlimit
`2
`This formula provides a fudge factor for connections that never complete and guaran-
`tees that l isten(fd, 0) allows one connection. See Figure 18.23 in Volume 1 for an
`additional discussion of this formula.
`Allocate new socket
`A new socket structure is allocated and initialized. If the process calls
`setsockopt for the listening socket, the connected socket inherits several socket
`options because so_options, so_linger, so_pgid, and the sb_hiwat values are
`copied into the new socket structure.
`Queue connection
`soqueue was set from connstatus on line 129. The new socket is inserted onto
`so_q0 if soqueue is 0 (e.g., TCP connections) or onto so_q if connstatus is nonzero
`(e.g., TP4 connections).
`Protocol processing
`The PRU_ATTACH request is issued to perform protocol layer processing on the new
`connection. If this fails, the socket is dequeued and discarded, and sonewconn returns
`a null pointer.
`Wakeup processes
`If connstatus is nonzero, any processes sleeping in accept or selecting for read-
`ability on the socket are awakened, connstatus is logically ORed with so_state.
`This code is never executed for TCP connections, since connstatus is always 0 for
`TCP.
`
`Protocols, such as TCP, that put incoming connections on so_q0 first, call
`soisconnected when the connection establishment phase completes. For TCP, this
`happens when the second SYN is ACKed on the connection.
`Figure 15.30 shows sei sconnec ted.
`Queue incomplete connections
`The socket state is changed to show that the connection has completed. When
`soisconnected is’called for incoming connections, (i.e., when the local process is call-
`ing accept), head is nonnull.
`If soqremque returns 1, the socket is queued on so_q and sorwakeup wakes up
`any processes using select to monitor the socket for connection arrival by testing for
`readability. If a process is blocked in accept waiting for the connection, wakeup
`causes the matching t s 1 e ep to return.
`
`WISTRON CORP. EXHIBIT 1013.489
`
`
`
`464
`
`Socket Layer
`
`78 soisconnected(so)
`79 struct socket *so;
`80 {
`81
`
`struct socket *head = so->so_head;
`
`SS_ISDISCONNECTING
`
`so->so_state &= -(SS_ISCONNECTING
`so->so_state I= SS_ISCONNECTED;
`if (head && soqremque(so, 0)) {
`soqinsque(head, so, I);
`sorwakeup(head);
`wakeup((caddr_t) & head->so_timeo);
`] else {
`wakeup((caddr_t) & so->so_timeo);
`sorwakeup(so);
`sowwakeup(so);
`
`82
`83
`84
`85
`86
`87
`88
`89
`90
`91
`92
`93 ]
`
`uipc_socket2.c
`
`] SS_ISCONFIRMING);
`
`]
`
`Figure 15.30 soisconnected function.
`
`uipc_socket2.c
`
`88--93
`
`Wakeup processes waiting for new connection
`If head is null, soqremque is not called since the process initiated the connection
`with the connect system call and the socket is not on a queue. If head is nonnull and
`soqremque returns 0, the socket is already on so_q. This happens with protocols such
`as TP4, which place connections on so_q before they are complete, wakeup awakens
`any process blocked in connect, and sorwakeup and sowwakeup take care of any
`processes that are using select to wait for the connection to complete.
`
`15.13 connect System call
`
`A server process calls the listen and accept system calls to wait for a remote process
`to initiate a connection. If the process wants to initiate a connection itself (i.e., a client),
`it calls connect.
`For connection-oriented protocols such as TCP, connect establishes a connection to
`the specified foreign address. The kernel selects and implicitly binds an address to the
`local socket if the process has not already done so with bind.
`For connectionless protocols such as UDP or ICMP, connect records the foreign
`address for use in sending future datagrams. Any previous foreign address is replaced
`with the new address.
`Figure 15.31 shows the functions called when connect is used for UDP or TCR
`The left side of the figure shows connect processing for connectionless protocols,
`such as UDP. In this case the protocol layer calls soisconnected and the connect
`system call returns immediately.
`The right side of the figure shows connect processing for connection-oriented pro-
`tocols, such as TCP. In this case, the protocol layer begins the connection establishment
`and calls soisconnecting to indicate that the connection will complete some time in
`the future. Unless the socket is nonblocking, soconnect calls tsleep to wait for the
`
`WISTRON CORP. EXHIBIT 1013.490
`
`
`
`G) ;
`
`t
`
`Section 15.13
`
`connect System call
`
`465
`
`_
`
`ECT request
`
`-
`
`TCP beglns three-way
`handshake
`
`~
`
`i
`~
`
`TCP three-way
`handshake completes
`
`....... -T~i~ connection
`establishment
`
`Figure 15.31 connect processing.
`
`connection to complete. For TCP, when the three-way handshake is complete, the
`protocol layer calls soisconnected to mark the socket as connected and then calls
`wakeup to awaken the process and complete the connect system call.
`
`180--188
`
`189--200
`
`201--208
`
`Figure 15.32 shows the connect system call.
`The three arguments to connect (in the connect_args structure) are: s, the
`socket descriptor; name, a pointer to a buffer containing the foreign address; and
`name 1 en, the length of the buffer.
`getsock returns the socket as usual. A connection request may already be pend-
`ing on a nonblocking socket, in which case EALREADY is returned, sockargs copies
`the foreign address from the process into the kernel.
`Start connection processing
`The connection attempt is started by calling soconnec t. If soconnect reports an
`error, connect jumps to bad. If a connection has not yet completed by the time
`soconnect returns and nonblocking I/O is enabled, EINPROGRESS is returned imme-
`diately to avoid waiting for the connection to complete. Since connection establishment
`
`WISTRON CORP. EXHIBIT 1013.491
`
`
`
`Socket Layer
`
`Chapter 15
`
`Se
`
`180 struct connect_args {
`181
`int
`s;
`182
`caddr_t name;
`183
`int
`namelen;
`184 ];
`
`185 connect(p, uap, retval)
`186 struct proc *p;
`187 struct connect_args *uap;
`188 int *retval;
`189 {
`190
`191
`192
`193
`
`struct file *fp;
`struct socket *so;
`struct mbuf *nam;
`int
`error, s;
`
`uipc_syscalls.c
`
`2O
`
`2.1
`
`if (error = getsock(p->p_fd, uap->s, &fp))
`return (error);
`so = (struct socket *) fp->f_data;
`if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
`return (EALREADY);
`if (error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME))
`return (error);
`
`error : Soconnect(so, nam);
`if (error)
`goto bad;
`if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
`m_freem(nam);
`return (EINPROGRESS);
`
`}s
`
` = splnet();
`while ((so->so_state & SS_ISCONNECTING) && so->so_error =: 0)
`if (error = tsleep((caddr_t) & so->so_timeo, PSOCK I PCATCH,
`netcon, 0))
`
`break;
`if (error == 0) {
`error : so->so_error;
`so->so_error : 0;
`
`}s
`
`plx(s);
`bad:
`so->so_state &= ~SS_ISCONNECTING;
`m_freem(nam);
`if (error == ERESTART)
`error = EINTR;
`return (error);
`
`194
`195
`196
`197
`198
`199
`200
`
`201
`2O2
`203
`204
`205
`206
`207
`208
`209
`210
`211
`212
`213
`214
`215
`216
`217
`218
`219
`220
`221
`222
`223
`224
`
`Figure 15.32 connect system call.
`
`uipc_syscalls.c
`
`WISTRON CORP. EXHIBIT 1013.492
`
`
`
`ler 15
`
`:alls.c
`
`alls.c
`
`Section 15.13
`
`connect System call 467
`
`normally involves exchanging several packets with the remote system, it may take a
`while to complete. Further calls to connect return EALREADY until the connection
`completes. ~.T SCONN is returned when the connection is complete.
`Wait for connection establishment
`The wh±le loop continues until the connection is established or an error occurs.
`splnet prevents connect from missing a wakeup between testing the state of the
`socket and the call to tsleep. After the loop, error contains 0, the error code from
`t s 3_eep, or the error from the socket.
`The SS_TSCONN~.CTING flag is cleared since the connection has completed or the
`attempt has failed. The mbuf containing the foreign address is released and any error is
`returned.
`
`208--21 7
`
`218--224
`
`soconnect Function
`
`This function ensures that the socket is in a valid state for a connection request. If the
`socket is not connected or a connection is not pending, then the connection request is
`always valid. If the socket is already connected or a connection is pending, the new
`connection request is rejected for connection-oriented protocols such as TCP. For con-
`nectionless protocols such as UDP, multiple connection requests are OK but each new
`request replaces the previous foreign address.
`Figure 15.33 shows the soconnee t function.
`
`uipc_socket.c
`
`198 soconnect(so, ham)
`199 struct socket *so;
`200 struct mbuf *nam;
`201 {
`202
`203
`
`int
`int
`
`s;
`error;
`if (so->so_options & SO_ACCEPTCONN)
`return (EOPNOTSUPP);
`s = splnet();
`/*
`* If protocol is connection-based, can only connect once.
`* Otherwise, if connected, try to disconnect first.
`* This allows user to disconnect by connecting to, e.g.,
`* a null address.
`*/
`if (so >so_state & (SS_ISCONNECTED I SS_ISCONNECTING) &&
`((so->so_proto->pr_flags & PR_CONNREQUIRED) I I
`(error = sodisconnect(so))))
`error = EISCONN;
`
`204
`205
`206
`207
`208
`209
`210
`211
`212
`213
`214
`215
`216
`217
`218
`219
`220
`221
`222
`
`else
`
`error : (*so->so_proto->pr_usrreq} (so, PRU_CONNECT,
`(struct mbuf *) 0, ham, (struct mbuf *) 0);
`
`splx(s);
`return (error);
`
`Figure 15.33 soconnect function.
`
`uipc_socket.c
`
`WISTRON CORP. EXHIBIT 1013.493
`
`
`
`468
`
`Socket Layer
`
`Chapter 15
`
`198-222
`
`soconnect returns EOPNOTSUPP if the socket is marked to accept connections,
`since a process cannot initiate connections if listen has already been called for the
`socket. EISCONN is returned if the protocol is connection oriented and a connection has
`already been initiated. For a connectionless protocol, any existing association with a
`foreign address is broken by sodi sconnect.
`The PRU_CONNECT request starts the appropriate protocol processing to establish
`the connection or the association.
`
`Breaking a Connectionless Association
`
`For connectionless protocols, the foreign address associated with a socket can be dis-
`carded by calling connect with an invalid name such as a pointer to a structure filled
`with 0s or a structure with an invalid size. sodisconnect removes a foreign address
`associated with the socket, and PRU_CONNECT returns an error such as EAFNOSUPPORT
`or EADDRNOTAVAIL, leaving the socket with no foreign address. This is a useful,
`although obscure, way of breaking the association between a connectionless socket and
`a foreign address without replacing it.
`
`15.14 shutdown System Call
`
`The shutdown system call, shown in Figure 15.34, closes the write-half, read-half, or
`both halves of a connection. For the read-half, shutdown discards any data the process
`hasn’t yet read and any data that arrives after the call to shutdown. For the write-half,
`shutdown lets the protocol specify the semantics. For TCP, any remaining data will be
`sent followed by a FIN. This is TCP’s half-close feature (Section 18.5 of Volume 1).
`To destroy the socket and release the descriptor, close must be called, close can
`also be called directly without first calling shutdown. As with all descriptors, close is
`called by the kernel for sockets that have not been closed when a process terminates.
`
`550 struct shutdown_args { uipc_syscalls.c
`551 int
`s;
`552
`int
`how;
`553 } ;
`554 shutdown(p, uap, retval)
`555 struct proc *p;
`556 struct shutdown_args *uap;
`557 int
`*retval;
`558 {
`559
`560
`
`struct file *fp;
`int
`error;
`
`561
`562
`563
`564 }
`
`if (error : getsock(p->p_fd, uap->s, &fp))
`return (error);
`return (soshutdown((struct socket *) fp->f_data, uap->how));
`
`Figure 15.34 shutdown system call.
`
`uipc_syscalls.c
`
`WISTRON CORP. EXHIBIT 1013.494
`
`
`
`15
`
`.S,
`le
`is
`a
`
`;h
`
`)r
`;s
`f,
`
`n
`
`.¢
`
`Section 15.14
`
`shutdown System Call 469
`
`550-557
`
`In the shutdown_args structure, s is the socket descriptor and how specifies
`which halves of the connection are to be closed. Figure 15.35 shows the expected values
`for how and how++ (which is used in Figure 15.36).
`
`how
`0
`1
`2
`
`how+ +
`Description
`FREAD
`shut down the read-half of the connection
`FWRITE
`shut down the write-half of the connection
`FREAD/FWRITE shut down both halves of the connection
`
`Figure 15.35 shutdown system call options,
`
`Notice that there is an implicit numerical relationship between how and the constants FREAD
`and FWRITE.
`
`558-564
`
`shutdown is a wrapper function for soshutdown. The socket associated with the
`descriptor is returned by getsock, soshutdown is called, and its value is returned.
`soshutdown and sorflush Functions
`
`The shut down of the read-half of a connection is handled in the socket layer by
`sorflush, and the shut down of the write-half of a connection is processed by the
`PRU_SHUTDOWN request in the protocol layer. The soshutdown function is shown in
`Figure 15.36.
`
`720 soshutdown(so, how)
`721 struct socket *so;
`722 int
`how;
`723 {
`724
`
`struct protosw *pr = so->so~Droto;
`
`uipc_socket.c
`
`725
`726
`727
`728
`729
`730
`731
`732
`
`how++;
`if (how & FREAD)
`sorflush(so);
`if (how & FWRITE)
`return
`(*pr->pr_usrreq) (so, PRU_SHUTDOWN,
`(struct mbuf *) 0, (struct mbuf *)
`O, (struct mbuf *) 0)) ;
`
`return (0);
`
`Figure 15.36 soshutdown function.
`
`uipc_socket, c
`
`720--732
`
`733--747
`
`If the read-half of the socket is being closed, sorflush, shown in Figure 15.37, dis-
`cards the data in the socket’s receive buffer and disables the read-half of the connection.
`If the write-half of the socket is being closed, the PRU_SHUTDOWN request is issued to
`the protocol.
`The process waits for a lock on the receive buffer. Because of SB_NOINTR, sblock
`does not return when an interrupt occurs, splimp blocks network interrupts and
`protocol processing while the socket is modified, since the receive buffer may be
`accessed by the protocol layer as it processes incoming packets.
`
`WISTRON CORP. EXHIBIT 1013.495
`
`
`
`47O
`
`Socket Layer
`
`733 sorflush(so)
`734 struct socket *so;
`735 {
`736
`737
`738
`739
`
`struct sockbuf *sb = &so->so_rcv;
`struct protosw *pr = so->so_proto;
`int
`s;
`struct sockbuf asb;
`
`Chapter 15
`
`uipc_socket.c
`
`740
`741
`742
`743
`744
`745
`746
`747
`
`748
`749
`750
`751
`
`sb->sb_flags ]: SB_NOINTR;
`(void) sblock(sb, M_WAITOK);
`s = splimp();
`socantrcvmore(so);
`sbunlock(sb);
`asb = *sb;
`bzero((caddr_t) sb, sizeof(*sb));
`splx(s);
`
`if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
`(*pr >pr_domain->dom_dispose) (asb.sb_mb);
`sbrelease(&asb);
`
`Figure 15.37 sorflush function.
`
`uipc_socket.c
`
`socantrcvmore marks the socket to reject incoming packets. A copy of the
`sockbuf structure is saved in asb to be used after interrupts are restored by splx.
`The original sockbuf structure is cleared by bzero, so that the receive queue appears
`to be empty.
`Release control mbufs
`Some kernel resources may be referenced by control information present in the
`receive queue when shutdown was called. The mbuf chain is still available through
`sb_mb in the copy Of the sockbuf structure.
`If the protocol supports access rights and has registered a dora_dispose function,
`it is called here to release these resources.
`
`748-751
`
`In the Unix domain it is possible to pass descriptors between processes with control messages.
`These messages contain pointers to reference counted data structures. The dora_dispose
`function takes care of discarding the references and the data structures if necessary to avoid
`creating an unreferenced structure and introducing a memory leak in the kernel. For more
`information on passing file descriptors within the Unix domain, see [Stevens 1990] and [Leffier
`et al. 1989].
`
`Any input data pending when shutdown is called is discarded when sbrelease
`releases any mbufs on the receive queue.
`Notice that the shut down of the read-half of the connection is processed entirely by
`the socket layer (Exercise 15.6) and the shut down of the write-half of the connection is
`handled by the protocol through the PRU_SHUTDOWN request. TCP responds to the
`PRU_SHUTDOWN by sending all queued data and then a FIN to close the write-half of the
`TCP connection.
`
`WISTRON CORP. EXHIBIT 1013.496
`
`
`
`Section 15.15
`
`close System Call 471
`
`15.15 close System Call
`
`The close system call works with any type of descriptor. When fd is the last descrip-
`tor that references the object, the object-specific c 1 o s e function is called:
`error = (*fp->f_ops->fo_close) (fp, p) ;
`
`As shown in Figure 15.]3, fp->f_ops->fo_close for a socket is the function
`soo_close.
`
`soo_close Function
`
`This function, shown in Figure 15.38, is a wrapper for the soclose function.
`
`152 soo_close(fp, p)
`153 struct file *fp;
`154 struct proc *p;
`155 {
`156
`
`int
`
`error = 0;
`
`157
`158
`159
`160
`161
`
`if (fp->f_data)
`error : soclose((struct socket *) fp->f_data);
`fp->f_data = 0;
`return (error);
`
`Figure 15.38 soo_close function.
`
`sys_socket.c
`
`sys_socket.c
`
`If a socket structure is associated with the file structure, soclose is called,
`f_data is cleared, and any posted error is returned.
`
`soclose Function
`
`This function aborts any connections that are pending on the socket (i.e., that have not
`yet been accepted by a process), waits for data to be transmitted to the foreign system,
`and releases the data structures that are no longer needed.
`soclose is shown in Figure 15.39.
`Discard pending connections
`If the socket was accepting connections, soc!ose traverses the two connection
`queues and calls soabort for each pending connection. If the protocol control block is
`null, the protocol has already been detached from the socket and s oc lose jumps to the
`cleanup code at d±scard.
`
`129--141
`
`soabort issues the PRU_ABORT request to the socket’s protocol and returns the result.
`soabort is not shown in this text. Figures 23.38 and 30.7 discuss how UDP and TCP handle
`this request.
`
`WISTRON CORP. EXHIBIT 1013.497
`
`
`
`472
`
`Socket Layer
`
`129 soclose(so)
`130 struct socket *so;
`131 {
`132
`133
`
`int
`int
`
`s : splnet();
`error = 0;
`
`Chapter 15
`
`uipc_socket.c
`
`/* conservative */
`
`if
`
`so->so_options & SO_ACCEPTCONN) {
`while (so->so_q0)
`(void) soabort(so->so_q0);
`while (so->so_q)
`(void) soabort(so->so_q);
`
`]i
`
`f (so->so_pcb == 0)
`goto discard;
`if (so->so_state & SS_ISCONNECTED) {
`if ((so->so_state & SS_ISDISCONNECTING) == 0) {
`error = sodisconnect(so);
`if (error)
`goto drop;
`
`}i
`
`f (so->so_options & SO_LINGER) {
`if ((so->so_state & SS_ISDISCONNECTING) &&
`(so->so_state & SS_NBIO))
`goto drop;
`while (so >so_state & SS_ISCONNECTED)
`if (error = tsleep((caddr_t) & so->so_timeo,
`PSOCK 1 PCATCH, netcls, so->so_linger)
`
`break;
`
`}
`
`}
`drop:
`if (so->so_pcb) {
`error2 :
`int
`(*so->so_proto->pr_usrreq) (so, PRU_DETACH,
`(struct mbuf *) 0, (struct mbuf *) 0, (struct mbuf *) 0)
`if (error == 0)
`error = error2;
`
`}
`discard:
`if (so->so_state & SS_NOFDREF)
`panic("soclose: NOFDREF");
`so->so_state [= SS_NOFDREF;
`sofree(so);
`splx(s);
`return (error);
`
`Figure 15.39 soclose function.
`
`uipc_socket.c
`
`134
`135
`136
`137
`138
`139
`140
`141
`142
`143
`144
`145
`146
`147
`148
`149
`150
`151
`152
`153
`154
`155
`156
`157
`158
`159
`160
`161
`162
`163
`164
`165
`166
`167
`168
`169
`170
`171
`172
`173 }
`
`WISTRON CORP. EXHIBIT 1013.498
`
`
`
`Section 15.15
`
`close System Call 473
`
`142-157
`
`Break established connection or association
`If the socket is not connected, execution continues at drop; otherwise the socket
`must be disconnected from its peer. If a disconnect is not in progress, sodisconnect
`starts the disconnection process. If the SO_LINGER socket option is set, soclose may
`need to wait for the disconnect to complete before returning. A nonblocking socket
`never waits for a disconnect to complete, so soclose jumps immediately to drop in
`that case. Otherwise, the connection termination is in progress and the SO_LINGER
`option indicates that soclose must wait some time for it to complete. The whi le loop
`continues until the disconnect completes, the linger time (so_l inger) expires, or a sig-
`nal is delivered to the process.
`
`158-173
`
`If the linger time is set to 0, tsleep returns only when the disconnect completes (perhaps
`because of an error) or a signal is delivered.
`Release data structures
`If the socket still has an attached protocol, the PRU_DETACH request breaks the con-
`nection between this socket and the protocol. Finally the socket is marked as not having
`an associated file descriptor, which allows s o free to release the socket.
`The sofree function is shown in Figure 15.40.
`
`ll0"sofree(so)
`iii struct socket *so;
`112 {
`
`uipc_socket.c
`
`113
`114
`115
`116
`117
`118
`119
`120
`121
`122
`123 }
`
`if (so->so_pcb [I (so->so_state & SS_NOFDREF) == 0)
`return;
`if (so->so_head)
`if (!soqremque(so, 0) && !soqremque(so, i))
`panic("sofree dq");
`so->so_head = 0;
`
`}
`sbrelease(&so->so_snd);
`sorflush(so) ;
`FREE(so, M_SOCKET);
`
`Figure 15.40 sofree function.
`
`uipc_socket.c
`
`110--114
`
`115--119
`
`Return if socket still in use
`If a protocol is still associated with the socket, or if the socket is still associated with
`a descriptor, sofree returns immediately.
`Remove from connection queues
`If the socket is on a connection queue (so_head is nonnull), soqremque is called
`to remove the socket. An attempt is made to remove the socket from the incomplete
`connection queue and if this fails, then from the completed connection queue. One of
`the removals must succeed or the kernel panics, since so_head was nonnull, so_head
`is cleared.
`
`WISTRON CORP. EXHIBIT 1013.499
`
`
`
`474
`
`Socket Layer
`
`Chapter 15
`
`:20-:23
`
`Discard send and receive queues
`sbrelease discards any buffers in the send queue and sorflush discards any
`buffers in the receive queue. Finally, the socket itself is released.
`
`15.16 Summary
`
`In this chapter we looked at all the system calls related to network operations. The sys-
`tem call mechanism was described, and we traced the calls until they entered the proto-
`col processing layer through the pr_usrreq function.
`While looking at the socket layer, we avoided any discussion of address formats,
`protocol semantics, or protocol implementations. In the upcoming chapters we tie
`together the link-layer processing and socket-layer processing by looking in detail at the
`implementation of the Internet protocols in the protocol processing layer.
`
`Exercises
`15.1 How can a process without superuser privileges gain access to a socket created by a super-
`user process?
`15.2 How can a process determine if the sockaddr buffer it provides to accept was too small
`to hold the foreign address returned by the call?
`15.3 A feature proposed for IPv6 sockets is to have accept and recvfrom return a source
`route as an array of 128-bit IPv6 addresses instead of a single peer address. Since the array
`will not fit in a single mbuf, modify accept and recvfrom to handle an mbuf chain from
`the protocol layer instead of a single mbuf. Will the existing code work if the protocol
`layer returns the array in an mbuf cluster instead of a chain of mbufs?
`15.4 Why is panic called when soqrernque returns a null pointer in Figure 15.26?
`15.5 Why does sorflush make a copy of the receive buffer?
`15.6 What happens when additional data is received after sorflush has zeroed the socket’s
`receive buffer? Read Chapter 16 before attempting this exercise.
`
`WISTRON CORP. EXHIBIT 1013.500
`
`
`
`Socket I/0
`
`16.1
`
`Introduction
`
`In this chapter we discuss the system calls that read and write data on a network con-
`nection. The chapter is divided into three parts.
`The first part covers the four system calls for sending data: wr±te, wr±tev,
`senc]to, and sendmsg. The second part covers the four system calls for receiving data:
`read, ready, recvfrom, and recvmsg. The third part of the chapter covers the
`select system call, which provides a standard way to monitor the status of descriptors
`in general and sockets in particular.
`The core of the socket layer is the sosend and soreceive functions. They handle
`all I/O between the socket layer and the protocol layer. As we’ll see, the semantics of
`the various types of protocols overlap in these functions, making the functions long and
`complex.
`
`16.2
`
`Code Introduction
`
`The three headers and four C files listed in Figure 16.1 are covered in this chapter.
`
`Global
`
`Variables
`
`The first two global variables shown in Figure 16.2 are used by the se]_ect system call.
`The third global variable controls the amount of memory allocated to a socket.
`
`475
`
`WISTRON CORP. EXHIBIT 1013.501
`
`
`
`476
`
`Socket I/O
`
`Chapter 16
`
`File
`sys/s o eke t. h
`sys/socketvar, h
`sys / ui o. h
`kern/uipc_syscalls, c
`kern/uipc_socket, c
`kern/sys_generic, c
`kern / sys_s ocke t. c
`
`Description
`structures and macro for sockets API
`socket structure and macros
`u i o structure definition
`socket system calls
`socket layer processing
`select system call
`s e I ec t processing for sockets
`
`Figure 16.1 Files discussed in this chapter.
`
`Datatype
`Variable
`wait channel for select
`int
`selwai t
`nselcol i int flag used to avoid race conditions in select
`sb max u_l ong maximum number of bytes to a11ocate for a socket receive or send buffer
`
`Description
`
`Figure 16.2 Global variables introduced in this chapter.
`
`16.3
`
`Socket Buffers
`
`Section 15.3 showed that each socket has an associated send and receive buffer. The
`sockbuf structure definition from Figure 15.5 is repeated in Figure 16.3.
`
`72
`73
`74
`75
`76
`77
`78
`79
`80
`81
`82
`
`struct sockbuf {
`u_long
`sb_cc;
`u_long
`sb_hiwat;
`u_long
`sb_mbcnt;
`u_long sb_mbmax;
`long
`sb_lowat;
`struct mbuf *sb_mb;
`struct selinfo sb_sel;
`sb_flags;
`short
`short
`sb_timeo;
`} so_rcv, so_snd;
`
`/* actual chars in buffer */
`/* max actual char count */
`/* chars of mbufs used */
`/* max chars of mbufs to use */
`/* low water mark */
`/* the mbuf chain */
`/* process selecting read/write */
`/* Figure 16.5 */
`/* timeout for read/write */
`
`socketvar.h
`
`socketvar.h
`
`Figure 16.3 sockbuf structure.
`
`72--78
`
`Each buffer contains control information as well as pointers to data stored in mbuf
`chains, sb mb points to the first mbuf in the chain, and sb_cc is the total number of
`data bytes contained within the mbufs, sb_hiwat and sb_lowat regulate the socket
`flow control algorithms, sb_mbcnt is the total amount of memory allocated to the
`mbufs in the buffer.
`Recall that each mbuf may store from 0 to 2048 bytes of data (if an external cluster is
`used), sb_mbmax is an upper bound on the amount of memory to be allocated as
`
`WISTRON CORP. EXHIBIT 1013.502
`
`
`
`Section 16.3
`
`Socket Buffers 477
`
`mbufs for each socket buffer. Default limits are specified by each protocol when the
`PRU_ATTACH request is issued by the socket system call. The high-water and low-
`water marks may be modified by the process as long as the kernel-enforced hard limit
`of 262,144 bytes per socket buffer (sb_max) is not exceeded. The buffering algorithms
`are described in Sections 16.7 and 16.12. Figure 16.4 shows the default settings for the
`Internet protocols.
`
`Protocol
`
`UDP
`TCP
`raw IP
`ICMP
`IGMP
`
`sb_hiwat
`9 x 1024
`8 x 1024
`
`s o_snd
`sb_lowat
`2048 (ignored)
`2048
`
`sb_mbraax
`2 x sb_hiwat
`2 x sb_hiwat
`
`sb_hiwat
`40 x (1024 + 16)
`8 x I024
`
`s o_r cv
`sb lowat
`1
`1
`
`sb mbmax
`2 x sb_hiwat
`2xsb hiwat
`
`8 x 1024
`
`2048 (ignored)
`
`2 x sb_hiwat
`
`8 x 1024
`
`1
`
`2 x sb_hiwat
`
`Figure 16.4 Default socket buffer limits for the Internet protocols.
`
`Since the source address of each incoming UDP datagram is queued with the data
`(Section 23.8), the default UDP value for sb_hiwat is set to accommodate 40 1K data.-
`grams and thei