new calling convension for system calls
[unix-history] / usr / src / sys / kern / uipc_socket2.c
CommitLineData
da7c5cc6 1/*
83866636 2 * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
5b519e94 3 * All rights reserved.
da7c5cc6 4 *
5b519e94 5 * Redistribution and use in source and binary forms are permitted
616d42db
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5b519e94 16 *
c1aac372 17 * @(#)uipc_socket2.c 7.12 (Berkeley) %G%
da7c5cc6 18 */
681ebb17 19
94368568
JB
20#include "param.h"
21#include "systm.h"
94368568
JB
22#include "user.h"
23#include "proc.h"
24#include "file.h"
94368568 25#include "buf.h"
a8a7f6b3 26#include "malloc.h"
94368568
JB
27#include "mbuf.h"
28#include "protosw.h"
29#include "socket.h"
30#include "socketvar.h"
681ebb17
BJ
31
32/*
33 * Primitive routines for operating on sockets and socket buffers
34 */
35
83866636
MK
36/* strings for sleep message: */
37char netio[] = "netio";
38char netcon[] = "netcon";
39char netcls[] = "netcls";
40
41u_long sb_max = SB_MAX; /* patchable */
42
681ebb17
BJ
43/*
44 * Procedures to manipulate state flags of socket
2deddea9
BJ
45 * and do appropriate wakeups. Normal sequence from the
46 * active (originating) side is that soisconnecting() is
47 * called during processing of connect() call,
4c078bb2
BJ
48 * resulting in an eventual call to soisconnected() if/when the
49 * connection is established. When the connection is torn down
50 * soisdisconnecting() is called during processing of disconnect() call,
51 * and soisdisconnected() is called when the connection to the peer
52 * is totally severed. The semantics of these routines are such that
53 * connectionless protocols can call soisconnected() and soisdisconnected()
54 * only, bypassing the in-progress calls when setting up a ``connection''
55 * takes no time.
56 *
88a7a62a
SL
57 * From the passive side, a socket is created with
58 * two queues of sockets: so_q0 for connections in progress
2deddea9
BJ
59 * and so_q for connections already made and awaiting user acceptance.
60 * As a protocol is preparing incoming connections, it creates a socket
61 * structure queued on so_q0 by calling sonewconn(). When the connection
62 * is established, soisconnected() is called, and transfers the
63 * socket structure to so_q, making it available to accept().
64 *
88a7a62a 65 * If a socket is closed with sockets on either
2deddea9
BJ
66 * so_q0 or so_q, these sockets are dropped.
67 *
88a7a62a 68 * If higher level protocols are implemented in
4c078bb2 69 * the kernel, the wakeups done here will sometimes
88a7a62a 70 * cause software-interrupt process scheduling.
681ebb17 71 */
4c078bb2 72
681ebb17 73soisconnecting(so)
88a7a62a 74 register struct socket *so;
681ebb17
BJ
75{
76
77 so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
78 so->so_state |= SS_ISCONNECTING;
681ebb17
BJ
79}
80
81soisconnected(so)
88a7a62a 82 register struct socket *so;
681ebb17 83{
2deddea9 84 register struct socket *head = so->so_head;
681ebb17 85
3b61a902
MK
86 so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
87 so->so_state |= SS_ISCONNECTED;
88 if (head && soqremque(so, 0)) {
2deddea9 89 soqinsque(head, so, 1);
ab303321 90 sorwakeup(head);
88a7a62a 91 wakeup((caddr_t)&head->so_timeo);
3b61a902
MK
92 } else {
93 wakeup((caddr_t)&so->so_timeo);
94 sorwakeup(so);
95 sowwakeup(so);
2deddea9 96 }
681ebb17
BJ
97}
98
99soisdisconnecting(so)
88a7a62a 100 register struct socket *so;
681ebb17
BJ
101{
102
72857acf 103 so->so_state &= ~SS_ISCONNECTING;
681ebb17
BJ
104 so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
105 wakeup((caddr_t)&so->so_timeo);
4c078bb2 106 sowwakeup(so);
b454c3ea 107 sorwakeup(so);
681ebb17
BJ
108}
109
110soisdisconnected(so)
88a7a62a 111 register struct socket *so;
681ebb17
BJ
112{
113
114 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
115 so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
116 wakeup((caddr_t)&so->so_timeo);
117 sowwakeup(so);
118 sorwakeup(so);
119}
120
2deddea9
BJ
121/*
122 * When an attempt at a new connection is noted on a socket
123 * which accepts connections, sonewconn is called. If the
124 * connection is possible (subject to space constraints, etc.)
125 * then we allocate a new structure, propoerly linked into the
126 * data structure of the original socket, and return this.
3b61a902 127 * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
83866636
MK
128 *
129 * Currently, sonewconn() is defined as sonewconn1() in socketvar.h
130 * to catch calls that are missing the (new) second parameter.
2deddea9
BJ
131 */
132struct socket *
83866636 133sonewconn1(head, connstatus)
2deddea9 134 register struct socket *head;
3b61a902 135 int connstatus;
2deddea9
BJ
136{
137 register struct socket *so;
3b61a902 138 int soqueue = connstatus ? 1 : 0;
2deddea9
BJ
139
140 if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
0402489b
MK
141 return ((struct socket *)0);
142 MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
143 if (so == NULL)
144 return ((struct socket *)0);
145 bzero((caddr_t)so, sizeof(*so));
2deddea9
BJ
146 so->so_type = head->so_type;
147 so->so_options = head->so_options &~ SO_ACCEPTCONN;
148 so->so_linger = head->so_linger;
f7428e88 149 so->so_state = head->so_state | SS_NOFDREF;
2deddea9
BJ
150 so->so_proto = head->so_proto;
151 so->so_timeo = head->so_timeo;
6868eb98 152 so->so_pgid = head->so_pgid;
a8a7f6b3 153 (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
3b61a902 154 soqinsque(head, so, soqueue);
88a7a62a
SL
155 if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
156 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
3b61a902 157 (void) soqremque(so, soqueue);
0402489b
MK
158 (void) free((caddr_t)so, M_SOCKET);
159 return ((struct socket *)0);
2deddea9 160 }
3b61a902
MK
161 if (connstatus) {
162 sorwakeup(head);
163 wakeup((caddr_t)&head->so_timeo);
164 so->so_state |= connstatus;
165 }
2deddea9 166 return (so);
2deddea9
BJ
167}
168
169soqinsque(head, so, q)
170 register struct socket *head, *so;
171 int q;
172{
173
83866636 174 register struct socket **prev;
2deddea9
BJ
175 so->so_head = head;
176 if (q == 0) {
177 head->so_q0len++;
3b61a902
MK
178 so->so_q0 = 0;
179 for (prev = &(head->so_q0); *prev; )
180 prev = &((*prev)->so_q0);
2deddea9
BJ
181 } else {
182 head->so_qlen++;
3b61a902
MK
183 so->so_q = 0;
184 for (prev = &(head->so_q); *prev; )
185 prev = &((*prev)->so_q);
2deddea9 186 }
3b61a902 187 *prev = so;
2deddea9
BJ
188}
189
190soqremque(so, q)
191 register struct socket *so;
192 int q;
193{
194 register struct socket *head, *prev, *next;
195
196 head = so->so_head;
197 prev = head;
198 for (;;) {
199 next = q ? prev->so_q : prev->so_q0;
200 if (next == so)
201 break;
3b61a902 202 if (next == 0)
2deddea9
BJ
203 return (0);
204 prev = next;
205 }
206 if (q == 0) {
207 prev->so_q0 = next->so_q0;
208 head->so_q0len--;
209 } else {
210 prev->so_q = next->so_q;
211 head->so_qlen--;
212 }
213 next->so_q0 = next->so_q = 0;
214 next->so_head = 0;
215 return (1);
216}
217
4c078bb2
BJ
218/*
219 * Socantsendmore indicates that no more data will be sent on the
220 * socket; it would normally be applied to a socket when the user
221 * informs the system that no more data is to be sent, by the protocol
222 * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data
223 * will be received, and will normally be applied to the socket by a
224 * protocol when it detects that the peer will send no more data.
225 * Data queued for reading in the socket may yet be read.
226 */
227
ae921915
BJ
228socantsendmore(so)
229 struct socket *so;
230{
231
232 so->so_state |= SS_CANTSENDMORE;
233 sowwakeup(so);
234}
235
236socantrcvmore(so)
237 struct socket *so;
238{
239
240 so->so_state |= SS_CANTRCVMORE;
241 sorwakeup(so);
242}
243
681ebb17 244/*
4c078bb2
BJ
245 * Socket select/wakeup routines.
246 */
247
681ebb17
BJ
248/*
249 * Queue a process for a select on a socket buffer.
250 */
251sbselqueue(sb)
252 struct sockbuf *sb;
253{
a8a7f6b3 254 struct proc *p;
681ebb17 255
ae921915 256 if ((p = sb->sb_sel) && p->p_wchan == (caddr_t)&selwait)
681ebb17
BJ
257 sb->sb_flags |= SB_COLL;
258 else
259 sb->sb_sel = u.u_procp;
260}
261
ae921915
BJ
262/*
263 * Wait for data to arrive at/drain from a socket buffer.
264 */
265sbwait(sb)
266 struct sockbuf *sb;
267{
268
269 sb->sb_flags |= SB_WAIT;
83866636
MK
270 return (tsleep((caddr_t)&sb->sb_cc,
271 (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio,
272 sb->sb_timeo));
273}
274
275/*
276 * Lock a sockbuf already known to be locked;
277 * return any error returned from sleep (EINTR).
278 */
279sb_lock(sb)
280 register struct sockbuf *sb;
281{
282 int error;
283
284 while (sb->sb_flags & SB_LOCK) {
285 sb->sb_flags |= SB_WANT;
286 if (error = tsleep((caddr_t)&sb->sb_flags,
287 (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK|PCATCH,
288 netio, 0))
289 return (error);
290 }
291 sb->sb_flags |= SB_LOCK;
292 return (0);
ae921915
BJ
293}
294
681ebb17
BJ
295/*
296 * Wakeup processes waiting on a socket buffer.
a8a7f6b3
MK
297 * Do asynchronous notification via SIGIO
298 * if the socket has the SS_ASYNC flag set.
681ebb17 299 */
a8a7f6b3
MK
300sowakeup(so, sb)
301 register struct socket *so;
88a7a62a 302 register struct sockbuf *sb;
681ebb17 303{
0402489b 304 struct proc *p;
681ebb17
BJ
305
306 if (sb->sb_sel) {
307 selwakeup(sb->sb_sel, sb->sb_flags & SB_COLL);
308 sb->sb_sel = 0;
309 sb->sb_flags &= ~SB_COLL;
310 }
311 if (sb->sb_flags & SB_WAIT) {
312 sb->sb_flags &= ~SB_WAIT;
388ca8bd 313 wakeup((caddr_t)&sb->sb_cc);
681ebb17 314 }
8f7109aa 315 if (so->so_state & SS_ASYNC) {
6868eb98
MT
316 if (so->so_pgid < 0)
317 gsignal(-so->so_pgid, SIGIO);
318 else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
8f7109aa
EC
319 psignal(p, SIGIO);
320 }
321}
322
4c078bb2
BJ
323/*
324 * Socket buffer (struct sockbuf) utility routines.
325 *
326 * Each socket contains two socket buffers: one for sending data and
327 * one for receiving data. Each buffer contains a queue of mbufs,
328 * information about the number of mbufs and amount of data in the
329 * queue, and other fields allowing select() statements and notification
330 * on data availability to be implemented.
331 *
261a8548
MK
332 * Data stored in a socket buffer is maintained as a list of records.
333 * Each record is a list of mbufs chained together with the m_next
a8a7f6b3 334 * field. Records are chained together with the m_nextpkt field. The upper
261a8548
MK
335 * level routine soreceive() expects the following conventions to be
336 * observed when placing information in the receive buffer:
337 *
338 * 1. If the protocol requires each message be preceded by the sender's
339 * name, then a record containing that name must be present before
340 * any associated data (mbuf's must be of type MT_SONAME).
341 * 2. If the protocol supports the exchange of ``access rights'' (really
342 * just additional data associated with the message), and there are
343 * ``rights'' to be received, then a record containing this data
344 * should be present (mbuf's must be of type MT_RIGHTS).
345 * 3. If a name or rights record exists, then it must be followed by
346 * a data record, perhaps of zero length.
347 *
4c078bb2 348 * Before using a new socket structure it is first necessary to reserve
07680231 349 * buffer space to the socket, by calling sbreserve(). This should commit
4c078bb2 350 * some of the available buffer space in the system buffer pool for the
07680231
MK
351 * socket (currently, it does nothing but enforce limits). The space
352 * should be released by calling sbrelease() when the socket is destroyed.
4c078bb2
BJ
353 */
354
0e18ec4a 355soreserve(so, sndcc, rcvcc)
88a7a62a 356 register struct socket *so;
07680231 357 u_long sndcc, rcvcc;
0e18ec4a
BJ
358{
359
360 if (sbreserve(&so->so_snd, sndcc) == 0)
361 goto bad;
362 if (sbreserve(&so->so_rcv, rcvcc) == 0)
363 goto bad2;
83866636
MK
364 if (so->so_rcv.sb_lowat == 0)
365 so->so_rcv.sb_lowat = 1;
366 if (so->so_snd.sb_lowat == 0)
367 so->so_snd.sb_lowat = MCLBYTES;
368 if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
369 so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
0e18ec4a
BJ
370 return (0);
371bad2:
372 sbrelease(&so->so_snd);
373bad:
374 return (ENOBUFS);
375}
376
681ebb17
BJ
377/*
378 * Allot mbufs to a sockbuf.
83866636 379 * Attempt to scale mbmax so that mbcnt doesn't become limiting
bbfd9898 380 * if buffering efficiency is near the normal case.
681ebb17
BJ
381 */
382sbreserve(sb, cc)
383 struct sockbuf *sb;
07680231 384 u_long cc;
681ebb17
BJ
385{
386
83866636 387 if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES))
1ceef2d8 388 return (0);
d028a086 389 sb->sb_hiwat = cc;
83866636
MK
390 sb->sb_mbmax = min(cc * 2, sb_max);
391 if (sb->sb_lowat > sb->sb_hiwat)
392 sb->sb_lowat = sb->sb_hiwat;
ae921915 393 return (1);
681ebb17
BJ
394}
395
396/*
397 * Free mbufs held by a socket, and reserved mbuf space.
398 */
399sbrelease(sb)
400 struct sockbuf *sb;
401{
402
403 sbflush(sb);
d028a086 404 sb->sb_hiwat = sb->sb_mbmax = 0;
681ebb17
BJ
405}
406
407/*
261a8548
MK
408 * Routines to add and remove
409 * data from an mbuf queue.
c34d38f4
MK
410 *
411 * The routines sbappend() or sbappendrecord() are normally called to
412 * append new mbufs to a socket buffer, after checking that adequate
413 * space is available, comparing the function sbspace() with the amount
414 * of data to be added. sbappendrecord() differs from sbappend() in
415 * that data supplied is treated as the beginning of a new record.
416 * To place a sender's address, optional access rights, and data in a
417 * socket receive buffer, sbappendaddr() should be used. To place
418 * access rights and data in a socket receive buffer, sbappendrights()
419 * should be used. In either case, the new data begins a new record.
420 * Note that unlike sbappend() and sbappendrecord(), these routines check
421 * for the caller that there will be enough space to store the data.
422 * Each fails if there is not enough space, or if it cannot find mbufs
423 * to store additional information in.
424 *
425 * Reliable protocols may use the socket send buffer to hold data
426 * awaiting acknowledgement. Data is normally copied from a socket
427 * send buffer in a protocol with m_copy for output to a peer,
428 * and then removing the data from the socket buffer with sbdrop()
429 * or sbdroprecord() when the data is acknowledged by the peer.
681ebb17
BJ
430 */
431
432/*
261a8548
MK
433 * Append mbuf chain m to the last record in the
434 * socket buffer sb. The additional space associated
435 * the mbuf chain is recorded in sb. Empty mbufs are
436 * discarded and mbufs are compacted where possible.
681ebb17
BJ
437 */
438sbappend(sb, m)
261a8548
MK
439 struct sockbuf *sb;
440 struct mbuf *m;
681ebb17 441{
e495e1cc 442 register struct mbuf *n;
681ebb17 443
261a8548
MK
444 if (m == 0)
445 return;
446 if (n = sb->sb_mb) {
a8a7f6b3
MK
447 while (n->m_nextpkt)
448 n = n->m_nextpkt;
e495e1cc 449 while (n->m_next)
3b61a902
MK
450 if (n->m_flags & M_EOR) {
451 sbappendrecord(sb, m); /* XXXXXX!!!! */
452 return;
453 } else
454 n = n->m_next;
681ebb17 455 }
261a8548 456 sbcompress(sb, m, n);
681ebb17
BJ
457}
458
4c078bb2 459/*
261a8548
MK
460 * As above, except the mbuf chain
461 * begins a new record.
4c078bb2 462 */
261a8548
MK
463sbappendrecord(sb, m0)
464 register struct sockbuf *sb;
465 register struct mbuf *m0;
2b4b57cd 466{
2b4b57cd 467 register struct mbuf *m;
2b4b57cd 468
261a8548
MK
469 if (m0 == 0)
470 return;
471 if (m = sb->sb_mb)
a8a7f6b3
MK
472 while (m->m_nextpkt)
473 m = m->m_nextpkt;
261a8548
MK
474 /*
475 * Put the first mbuf on the queue.
476 * Note this permits zero length records.
477 */
478 sballoc(sb, m0);
479 if (m)
a8a7f6b3 480 m->m_nextpkt = m0;
261a8548
MK
481 else
482 sb->sb_mb = m0;
483 m = m0->m_next;
484 m0->m_next = 0;
0402489b
MK
485 if (m && (m0->m_flags & M_EOR)) {
486 m0->m_flags &= ~M_EOR;
487 m->m_flags |= M_EOR;
488 }
489 sbcompress(sb, m, m0);
490}
491
492/*
493 * As above except that OOB data
494 * is inserted at the beginning of the sockbuf,
495 * but after any other OOB data.
496 */
497sbinsertoob(sb, m0)
498 register struct sockbuf *sb;
499 register struct mbuf *m0;
500{
501 register struct mbuf *m;
502 register struct mbuf **mp;
503
504 if (m0 == 0)
505 return;
506 for (mp = &sb->sb_mb; m = *mp; mp = &((*mp)->m_nextpkt)) {
507 again:
508 switch (m->m_type) {
509
510 case MT_OOBDATA:
511 continue; /* WANT next train */
512
513 case MT_CONTROL:
514 if (m = m->m_next)
515 goto again; /* inspect THIS train further */
516 }
517 break;
518 }
519 /*
520 * Put the first mbuf on the queue.
521 * Note this permits zero length records.
522 */
523 sballoc(sb, m0);
524 m0->m_nextpkt = *mp;
525 *mp = m0;
526 m = m0->m_next;
527 m0->m_next = 0;
528 if (m && (m0->m_flags & M_EOR)) {
529 m0->m_flags &= ~M_EOR;
530 m->m_flags |= M_EOR;
531 }
261a8548
MK
532 sbcompress(sb, m, m0);
533}
534
535/*
c1aac372 536 * Append address and data, and optionally, control (ancillary) data
a8a7f6b3 537 * to the receive queue of a socket. If present,
c1aac372
MK
538 * m0 must include a packet header with total length.
539 * Returns 0 if no space in sockbuf or insufficient mbufs.
261a8548 540 */
c1aac372 541sbappendaddr(sb, asa, m0, control)
261a8548
MK
542 register struct sockbuf *sb;
543 struct sockaddr *asa;
c1aac372 544 struct mbuf *m0, *control;
261a8548
MK
545{
546 register struct mbuf *m, *n;
0402489b 547 int space = asa->sa_len;
261a8548 548
a8a7f6b3
MK
549if (m0 && (m0->m_flags & M_PKTHDR) == 0)
550panic("sbappendaddr");
551 if (m0)
552 space += m0->m_pkthdr.len;
c1aac372
MK
553 for (n = control; n; n = n->m_next) {
554 space += n->m_len;
555 if (n->m_next == 0) /* keep pointer to last control buf */
556 break;
557 }
261a8548 558 if (space > sbspace(sb))
2b4b57cd 559 return (0);
c1aac372
MK
560 if (asa->sa_len > MLEN)
561 return (0);
c34d38f4 562 MGET(m, M_DONTWAIT, MT_SONAME);
261a8548 563 if (m == 0)
2b4b57cd 564 return (0);
0402489b
MK
565 m->m_len = asa->sa_len;
566 bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
c1aac372
MK
567 if (n)
568 n->m_next = m0; /* concatenate data to control */
569 else
570 control = m0;
571 m->m_next = control;
572 for (n = m; n; n = n->m_next)
573 sballoc(sb, n);
261a8548 574 if (n = sb->sb_mb) {
a8a7f6b3
MK
575 while (n->m_nextpkt)
576 n = n->m_nextpkt;
577 n->m_nextpkt = m;
88a7a62a 578 } else
261a8548 579 sb->sb_mb = m;
261a8548
MK
580 return (1);
581}
582
c1aac372 583sbappendcontrol(sb, m0, control)
261a8548 584 struct sockbuf *sb;
c1aac372 585 struct mbuf *control, *m0;
261a8548
MK
586{
587 register struct mbuf *m, *n;
588 int space = 0;
589
c1aac372
MK
590 if (control == 0)
591 panic("sbappendcontrol");
592 for (m = control; ; m = m->m_next) {
593 space += m->m_len;
594 if (m->m_next == 0)
595 break;
596 }
597 n = m; /* save pointer to last control buffer */
c34d38f4 598 for (m = m0; m; m = m->m_next)
261a8548 599 space += m->m_len;
261a8548 600 if (space > sbspace(sb))
88a7a62a 601 return (0);
c1aac372
MK
602 n->m_next = m0; /* concatenate data to control */
603 for (m = control; m; m = m->m_next)
604 sballoc(sb, m);
261a8548 605 if (n = sb->sb_mb) {
a8a7f6b3
MK
606 while (n->m_nextpkt)
607 n = n->m_nextpkt;
c1aac372 608 n->m_nextpkt = control;
261a8548 609 } else
c1aac372 610 sb->sb_mb = control;
2b4b57cd
BJ
611 return (1);
612}
261a8548
MK
613
614/*
615 * Compress mbuf chain m into the socket
616 * buffer sb following mbuf n. If n
617 * is null, the buffer is presumed empty.
618 */
619sbcompress(sb, m, n)
620 register struct sockbuf *sb;
621 register struct mbuf *m, *n;
622{
0402489b 623 register int eor = 0;
c1aac372 624
261a8548 625 while (m) {
0402489b 626 eor |= m->m_flags & M_EOR;
261a8548
MK
627 if (m->m_len == 0) {
628 m = m_free(m);
629 continue;
630 }
0402489b 631 if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 &&
a8a7f6b3 632 (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] &&
c34d38f4 633 n->m_type == m->m_type) {
261a8548
MK
634 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
635 (unsigned)m->m_len);
636 n->m_len += m->m_len;
637 sb->sb_cc += m->m_len;
638 m = m_free(m);
639 continue;
640 }
261a8548
MK
641 if (n)
642 n->m_next = m;
643 else
644 sb->sb_mb = m;
0402489b 645 sballoc(sb, m);
261a8548 646 n = m;
0402489b 647 m->m_flags &= ~M_EOR;
261a8548
MK
648 m = m->m_next;
649 n->m_next = 0;
650 }
0402489b
MK
651 if (n)
652 n->m_flags |= eor;
261a8548 653}
2b4b57cd 654
681ebb17 655/*
261a8548
MK
656 * Free all mbufs in a sockbuf.
657 * Check that all resources are reclaimed.
681ebb17
BJ
658 */
659sbflush(sb)
88a7a62a 660 register struct sockbuf *sb;
681ebb17
BJ
661{
662
663 if (sb->sb_flags & SB_LOCK)
664 panic("sbflush");
acb7839f 665 while (sb->sb_mbcnt)
8011f5df 666 sbdrop(sb, (int)sb->sb_cc);
c1aac372 667 if (sb->sb_cc || sb->sb_mb)
681ebb17
BJ
668 panic("sbflush 2");
669}
670
671/*
261a8548 672 * Drop data from (the front of) a sockbuf.
681ebb17
BJ
673 */
674sbdrop(sb, len)
675 register struct sockbuf *sb;
676 register int len;
677{
261a8548
MK
678 register struct mbuf *m, *mn;
679 struct mbuf *next;
681ebb17 680
a8a7f6b3 681 next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
681ebb17 682 while (len > 0) {
261a8548
MK
683 if (m == 0) {
684 if (next == 0)
685 panic("sbdrop");
686 m = next;
a8a7f6b3 687 next = m->m_nextpkt;
261a8548
MK
688 continue;
689 }
b9f0d37f 690 if (m->m_len > len) {
681ebb17 691 m->m_len -= len;
a8a7f6b3 692 m->m_data += len;
681ebb17
BJ
693 sb->sb_cc -= len;
694 break;
695 }
b9f0d37f
BJ
696 len -= m->m_len;
697 sbfree(sb, m);
698 MFREE(m, mn);
699 m = mn;
681ebb17 700 }
082e4f86 701 while (m && m->m_len == 0) {
453677da 702 sbfree(sb, m);
082e4f86
MK
703 MFREE(m, mn);
704 m = mn;
705 }
261a8548
MK
706 if (m) {
707 sb->sb_mb = m;
a8a7f6b3 708 m->m_nextpkt = next;
261a8548
MK
709 } else
710 sb->sb_mb = next;
261a8548
MK
711}
712
713/*
714 * Drop a record off the front of a sockbuf
715 * and move the next record to the front.
716 */
261a8548
MK
717sbdroprecord(sb)
718 register struct sockbuf *sb;
719{
720 register struct mbuf *m, *mn;
721
722 m = sb->sb_mb;
723 if (m) {
a8a7f6b3 724 sb->sb_mb = m->m_nextpkt;
261a8548
MK
725 do {
726 sbfree(sb, m);
727 MFREE(m, mn);
728 } while (m = mn);
729 }
681ebb17 730}