This source file includes following definitions.
- soisconnecting
- soisconnected
- soisdisconnecting
- soisdisconnected
- sonewconn
- soqinsque
- soqremque
- socantsendmore
- socantrcvmore
- sbwait
- sb_lock
- sowakeup
- soreserve
- sbreserve
- sbcheckreserve
- sbrelease
- sblastrecordchk
- sblastmbufchk
- sbappend
- sbappendstream
- sbcheck
- sbappendrecord
- sbinsertoob
- sbappendaddr
- sbappendcontrol
- sbcompress
- sbflush
- sbdrop
- sbdroprecord
- sbcreatecontrol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <sys/file.h>
39 #include <sys/buf.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/signalvar.h>
46 #include <sys/event.h>
47
48
49
50
51
52
53 const char netcon[] = "netcon";
54 const char netcls[] = "netcls";
55 const char netio[] = "netio";
56 const char netlck[] = "netlck";
57
58 u_long sb_max = SB_MAX;
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 void
91 soisconnecting(struct socket *so)
92 {
93
94 so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
95 so->so_state |= SS_ISCONNECTING;
96 }
97
98 void
99 soisconnected(struct socket *so)
100 {
101 struct socket *head = so->so_head;
102
103 so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
104 so->so_state |= SS_ISCONNECTED;
105 if (head && soqremque(so, 0)) {
106 soqinsque(head, so, 1);
107 sorwakeup(head);
108 wakeup_one(&head->so_timeo);
109 } else {
110 wakeup(&so->so_timeo);
111 sorwakeup(so);
112 sowwakeup(so);
113 }
114 }
115
116 void
117 soisdisconnecting(struct socket *so)
118 {
119
120 so->so_state &= ~SS_ISCONNECTING;
121 so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
122 wakeup(&so->so_timeo);
123 sowwakeup(so);
124 sorwakeup(so);
125 }
126
127 void
128 soisdisconnected(struct socket *so)
129 {
130
131 so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
132 so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
133 wakeup(&so->so_timeo);
134 sowwakeup(so);
135 sorwakeup(so);
136 }
137
138
139
140
141
142
143
144
145
146
147
148 struct socket *
149 sonewconn(struct socket *head, int connstatus)
150 {
151 struct socket *so;
152 int soqueue = connstatus ? 1 : 0;
153 extern u_long unpst_sendspace, unpst_recvspace;
154 u_long snd_sb_hiwat, rcv_sb_hiwat;
155
156 splassert(IPL_SOFTNET);
157
158 if (mclpool.pr_nout > mclpool.pr_hardlimit * 95 / 100)
159 return ((struct socket *)0);
160 if (head->so_qlen + head->so_q0len > head->so_qlimit * 3)
161 return ((struct socket *)0);
162 so = pool_get(&socket_pool, PR_NOWAIT);
163 if (so == NULL)
164 return ((struct socket *)0);
165 bzero(so, sizeof(*so));
166 so->so_type = head->so_type;
167 so->so_options = head->so_options &~ SO_ACCEPTCONN;
168 so->so_linger = head->so_linger;
169 so->so_state = head->so_state | SS_NOFDREF;
170 so->so_proto = head->so_proto;
171 so->so_timeo = head->so_timeo;
172 so->so_pgid = head->so_pgid;
173 so->so_euid = head->so_euid;
174 so->so_ruid = head->so_ruid;
175 so->so_egid = head->so_egid;
176 so->so_rgid = head->so_rgid;
177 so->so_cpid = head->so_cpid;
178 so->so_siguid = head->so_siguid;
179 so->so_sigeuid = head->so_sigeuid;
180
181
182
183
184
185 snd_sb_hiwat = head->so_snd.sb_hiwat;
186 if (sbcheckreserve(snd_sb_hiwat, unpst_sendspace))
187 snd_sb_hiwat = unpst_sendspace;
188 rcv_sb_hiwat = head->so_rcv.sb_hiwat;
189 if (sbcheckreserve(rcv_sb_hiwat, unpst_recvspace))
190 rcv_sb_hiwat = unpst_recvspace;
191
192 (void) soreserve(so, snd_sb_hiwat, rcv_sb_hiwat);
193 soqinsque(head, so, soqueue);
194 if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
195 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
196 (void) soqremque(so, soqueue);
197 pool_put(&socket_pool, so);
198 return ((struct socket *)0);
199 }
200 if (connstatus) {
201 sorwakeup(head);
202 wakeup(&head->so_timeo);
203 so->so_state |= connstatus;
204 }
205 return (so);
206 }
207
208 void
209 soqinsque(struct socket *head, struct socket *so, int q)
210 {
211
212 #ifdef DIAGNOSTIC
213 if (so->so_onq != NULL)
214 panic("soqinsque");
215 #endif
216
217 so->so_head = head;
218 if (q == 0) {
219 head->so_q0len++;
220 so->so_onq = &head->so_q0;
221 } else {
222 head->so_qlen++;
223 so->so_onq = &head->so_q;
224 }
225 TAILQ_INSERT_TAIL(so->so_onq, so, so_qe);
226 }
227
228 int
229 soqremque(struct socket *so, int q)
230 {
231 struct socket *head;
232
233 head = so->so_head;
234 if (q == 0) {
235 if (so->so_onq != &head->so_q0)
236 return (0);
237 head->so_q0len--;
238 } else {
239 if (so->so_onq != &head->so_q)
240 return (0);
241 head->so_qlen--;
242 }
243 TAILQ_REMOVE(so->so_onq, so, so_qe);
244 so->so_onq = NULL;
245 so->so_head = NULL;
246 return (1);
247 }
248
249
250
251
252
253
254
255
256
257
258
259 void
260 socantsendmore(struct socket *so)
261 {
262
263 so->so_state |= SS_CANTSENDMORE;
264 sowwakeup(so);
265 }
266
267 void
268 socantrcvmore(struct socket *so)
269 {
270
271 so->so_state |= SS_CANTRCVMORE;
272 sorwakeup(so);
273 }
274
275
276
277
278 int
279 sbwait(struct sockbuf *sb)
280 {
281
282 sb->sb_flags |= SB_WAIT;
283 return (tsleep(&sb->sb_cc,
284 (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH, netio,
285 sb->sb_timeo));
286 }
287
288
289
290
291
292 int
293 sb_lock(struct sockbuf *sb)
294 {
295 int error;
296
297 while (sb->sb_flags & SB_LOCK) {
298 sb->sb_flags |= SB_WANT;
299 error = tsleep(&sb->sb_flags,
300 (sb->sb_flags & SB_NOINTR) ?
301 PSOCK : PSOCK|PCATCH, netlck, 0);
302 if (error)
303 return (error);
304 }
305 sb->sb_flags |= SB_LOCK;
306 return (0);
307 }
308
309
310
311
312
313
314 void
315 sowakeup(struct socket *so, struct sockbuf *sb)
316 {
317 selwakeup(&sb->sb_sel);
318 sb->sb_flags &= ~SB_SEL;
319 if (sb->sb_flags & SB_WAIT) {
320 sb->sb_flags &= ~SB_WAIT;
321 wakeup(&sb->sb_cc);
322 }
323 if (so->so_state & SS_ASYNC)
324 csignal(so->so_pgid, SIGIO, so->so_siguid, so->so_sigeuid);
325 KNOTE(&sb->sb_sel.si_note, 0);
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360 int
361 soreserve(struct socket *so, u_long sndcc, u_long rcvcc)
362 {
363
364 if (sbreserve(&so->so_snd, sndcc) == 0)
365 goto bad;
366 if (sbreserve(&so->so_rcv, rcvcc) == 0)
367 goto bad2;
368 if (so->so_rcv.sb_lowat == 0)
369 so->so_rcv.sb_lowat = 1;
370 if (so->so_snd.sb_lowat == 0)
371 so->so_snd.sb_lowat = MCLBYTES;
372 if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
373 so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
374 return (0);
375 bad2:
376 sbrelease(&so->so_snd);
377 bad:
378 return (ENOBUFS);
379 }
380
381
382
383
384
385
386 int
387 sbreserve(struct sockbuf *sb, u_long cc)
388 {
389
390 if (cc == 0 || cc > sb_max)
391 return (0);
392 sb->sb_hiwat = cc;
393 sb->sb_mbmax = min(cc * 2, sb_max + (sb_max / MCLBYTES) * MSIZE);
394 if (sb->sb_lowat > sb->sb_hiwat)
395 sb->sb_lowat = sb->sb_hiwat;
396 return (1);
397 }
398
399
400
401
402
403 int
404 sbcheckreserve(u_long cnt, u_long defcnt)
405 {
406 if (cnt > defcnt &&
407 mclpool.pr_nout> mclpool.pr_hardlimit / 2)
408 return (ENOBUFS);
409 return (0);
410 }
411
412
413
414
415 void
416 sbrelease(struct sockbuf *sb)
417 {
418
419 sbflush(sb);
420 sb->sb_hiwat = sb->sb_mbmax = 0;
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448 #ifdef SOCKBUF_DEBUG
449 void
450 sblastrecordchk(struct sockbuf *sb, const char *where)
451 {
452 struct mbuf *m = sb->sb_mb;
453
454 while (m && m->m_nextpkt)
455 m = m->m_nextpkt;
456
457 if (m != sb->sb_lastrecord) {
458 printf("sblastrecordchk: sb_mb %p sb_lastrecord %p last %p\n",
459 sb->sb_mb, sb->sb_lastrecord, m);
460 printf("packet chain:\n");
461 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt)
462 printf("\t%p\n", m);
463 panic("sblastrecordchk from %s", where);
464 }
465 }
466
467 void
468 sblastmbufchk(struct sockbuf *sb, const char *where)
469 {
470 struct mbuf *m = sb->sb_mb;
471 struct mbuf *n;
472
473 while (m && m->m_nextpkt)
474 m = m->m_nextpkt;
475
476 while (m && m->m_next)
477 m = m->m_next;
478
479 if (m != sb->sb_mbtail) {
480 printf("sblastmbufchk: sb_mb %p sb_mbtail %p last %p\n",
481 sb->sb_mb, sb->sb_mbtail, m);
482 printf("packet tree:\n");
483 for (m = sb->sb_mb; m != NULL; m = m->m_nextpkt) {
484 printf("\t");
485 for (n = m; n != NULL; n = n->m_next)
486 printf("%p ", n);
487 printf("\n");
488 }
489 panic("sblastmbufchk from %s", where);
490 }
491 }
492 #endif
493
494 #define SBLINKRECORD(sb, m0) \
495 do { \
496 if ((sb)->sb_lastrecord != NULL) \
497 (sb)->sb_lastrecord->m_nextpkt = (m0); \
498 else \
499 (sb)->sb_mb = (m0); \
500 (sb)->sb_lastrecord = (m0); \
501 } while (0)
502
503
504
505
506
507
508
509 void
510 sbappend(struct sockbuf *sb, struct mbuf *m)
511 {
512 struct mbuf *n;
513
514 if (m == NULL)
515 return;
516
517 SBLASTRECORDCHK(sb, "sbappend 1");
518
519 if ((n = sb->sb_lastrecord) != NULL) {
520
521
522
523
524
525 do {
526 if (n->m_flags & M_EOR) {
527 sbappendrecord(sb, m);
528 return;
529 }
530 } while (n->m_next && (n = n->m_next));
531 } else {
532
533
534
535
536 sb->sb_lastrecord = m;
537 }
538 sbcompress(sb, m, n);
539 SBLASTRECORDCHK(sb, "sbappend 2");
540 }
541
542
543
544
545
546
547 void
548 sbappendstream(struct sockbuf *sb, struct mbuf *m)
549 {
550
551 KDASSERT(m->m_nextpkt == NULL);
552 KASSERT(sb->sb_mb == sb->sb_lastrecord);
553
554 SBLASTMBUFCHK(sb, __func__);
555
556 sbcompress(sb, m, sb->sb_mbtail);
557
558 sb->sb_lastrecord = sb->sb_mb;
559 SBLASTRECORDCHK(sb, __func__);
560 }
561
562 #ifdef SOCKBUF_DEBUG
563 void
564 sbcheck(struct sockbuf *sb)
565 {
566 struct mbuf *m;
567 u_long len = 0, mbcnt = 0;
568
569 for (m = sb->sb_mb; m; m = m->m_next) {
570 len += m->m_len;
571 mbcnt += MSIZE;
572 if (m->m_flags & M_EXT)
573 mbcnt += m->m_ext.ext_size;
574 if (m->m_nextpkt)
575 panic("sbcheck nextpkt");
576 }
577 if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
578 printf("cc %lu != %lu || mbcnt %lu != %lu\n", len, sb->sb_cc,
579 mbcnt, sb->sb_mbcnt);
580 panic("sbcheck");
581 }
582 }
583 #endif
584
585
586
587
588
589 void
590 sbappendrecord(struct sockbuf *sb, struct mbuf *m0)
591 {
592 struct mbuf *m;
593
594 if (m0 == NULL)
595 return;
596
597
598
599
600
601 sballoc(sb, m0);
602 SBLASTRECORDCHK(sb, "sbappendrecord 1");
603 SBLINKRECORD(sb, m0);
604 m = m0->m_next;
605 m0->m_next = NULL;
606 if (m && (m0->m_flags & M_EOR)) {
607 m0->m_flags &= ~M_EOR;
608 m->m_flags |= M_EOR;
609 }
610 sbcompress(sb, m, m0);
611 SBLASTRECORDCHK(sb, "sbappendrecord 2");
612 }
613
614
615
616
617
618
619 void
620 sbinsertoob(struct sockbuf *sb, struct mbuf *m0)
621 {
622 struct mbuf *m, **mp;
623
624 if (m0 == NULL)
625 return;
626
627 SBLASTRECORDCHK(sb, "sbinsertoob 1");
628
629 for (mp = &sb->sb_mb; (m = *mp) != NULL; mp = &((*mp)->m_nextpkt)) {
630 again:
631 switch (m->m_type) {
632
633 case MT_OOBDATA:
634 continue;
635
636 case MT_CONTROL:
637 if ((m = m->m_next) != NULL)
638 goto again;
639 }
640 break;
641 }
642
643
644
645
646 sballoc(sb, m0);
647 m0->m_nextpkt = *mp;
648 if (*mp == NULL) {
649
650 sb->sb_lastrecord = m0;
651 }
652 *mp = m0;
653 m = m0->m_next;
654 m0->m_next = NULL;
655 if (m && (m0->m_flags & M_EOR)) {
656 m0->m_flags &= ~M_EOR;
657 m->m_flags |= M_EOR;
658 }
659 sbcompress(sb, m, m0);
660 SBLASTRECORDCHK(sb, "sbinsertoob 2");
661 }
662
663
664
665
666
667
668
669 int
670 sbappendaddr(struct sockbuf *sb, struct sockaddr *asa, struct mbuf *m0,
671 struct mbuf *control)
672 {
673 struct mbuf *m, *n, *nlast;
674 int space = asa->sa_len;
675
676 if (m0 && (m0->m_flags & M_PKTHDR) == 0)
677 panic("sbappendaddr");
678 if (m0)
679 space += m0->m_pkthdr.len;
680 for (n = control; n; n = n->m_next) {
681 space += n->m_len;
682 if (n->m_next == NULL)
683 break;
684 }
685 if (space > sbspace(sb))
686 return (0);
687 if (asa->sa_len > MLEN)
688 return (0);
689 MGET(m, M_DONTWAIT, MT_SONAME);
690 if (m == NULL)
691 return (0);
692 m->m_len = asa->sa_len;
693 bcopy(asa, mtod(m, caddr_t), asa->sa_len);
694 if (n)
695 n->m_next = m0;
696 else
697 control = m0;
698 m->m_next = control;
699
700 SBLASTRECORDCHK(sb, "sbappendaddr 1");
701
702 for (n = m; n->m_next != NULL; n = n->m_next)
703 sballoc(sb, n);
704 sballoc(sb, n);
705 nlast = n;
706 SBLINKRECORD(sb, m);
707
708 sb->sb_mbtail = nlast;
709 SBLASTMBUFCHK(sb, "sbappendaddr");
710
711 SBLASTRECORDCHK(sb, "sbappendaddr 2");
712
713 return (1);
714 }
715
716 int
717 sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
718 {
719 struct mbuf *m, *mlast, *n;
720 int space = 0;
721
722 if (control == NULL)
723 panic("sbappendcontrol");
724 for (m = control; ; m = m->m_next) {
725 space += m->m_len;
726 if (m->m_next == NULL)
727 break;
728 }
729 n = m;
730 for (m = m0; m; m = m->m_next)
731 space += m->m_len;
732 if (space > sbspace(sb))
733 return (0);
734 n->m_next = m0;
735
736 SBLASTRECORDCHK(sb, "sbappendcontrol 1");
737
738 for (m = control; m->m_next != NULL; m = m->m_next)
739 sballoc(sb, m);
740 sballoc(sb, m);
741 mlast = m;
742 SBLINKRECORD(sb, control);
743
744 sb->sb_mbtail = mlast;
745 SBLASTMBUFCHK(sb, "sbappendcontrol");
746
747 SBLASTRECORDCHK(sb, "sbappendcontrol 2");
748
749 return (1);
750 }
751
752
753
754
755
756
757 void
758 sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n)
759 {
760 int eor = 0;
761 struct mbuf *o;
762
763 while (m) {
764 eor |= m->m_flags & M_EOR;
765 if (m->m_len == 0 &&
766 (eor == 0 ||
767 (((o = m->m_next) || (o = n)) &&
768 o->m_type == m->m_type))) {
769 if (sb->sb_lastrecord == m)
770 sb->sb_lastrecord = m->m_next;
771 m = m_free(m);
772 continue;
773 }
774 if (n && (n->m_flags & M_EOR) == 0 &&
775
776 m->m_len <= MCLBYTES / 4 &&
777 m->m_len <= M_TRAILINGSPACE(n) &&
778 n->m_type == m->m_type) {
779 bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
780 (unsigned)m->m_len);
781 n->m_len += m->m_len;
782 sb->sb_cc += m->m_len;
783 if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME)
784 sb->sb_datacc += m->m_len;
785 m = m_free(m);
786 continue;
787 }
788 if (n)
789 n->m_next = m;
790 else
791 sb->sb_mb = m;
792 sb->sb_mbtail = m;
793 sballoc(sb, m);
794 n = m;
795 m->m_flags &= ~M_EOR;
796 m = m->m_next;
797 n->m_next = NULL;
798 }
799 if (eor) {
800 if (n)
801 n->m_flags |= eor;
802 else
803 printf("semi-panic: sbcompress");
804 }
805 SBLASTMBUFCHK(sb, __func__);
806 }
807
808
809
810
811
812 void
813 sbflush(struct sockbuf *sb)
814 {
815
816 KASSERT((sb->sb_flags & SB_LOCK) == 0);
817
818 while (sb->sb_mbcnt)
819 sbdrop(sb, (int)sb->sb_cc);
820
821 KASSERT(sb->sb_cc == 0);
822 KASSERT(sb->sb_datacc == 0);
823 KASSERT(sb->sb_mb == NULL);
824 KASSERT(sb->sb_mbtail == NULL);
825 KASSERT(sb->sb_lastrecord == NULL);
826 }
827
828
829
830
831 void
832 sbdrop(struct sockbuf *sb, int len)
833 {
834 struct mbuf *m, *mn;
835 struct mbuf *next;
836
837 next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
838 while (len > 0) {
839 if (m == NULL) {
840 if (next == NULL)
841 panic("sbdrop");
842 m = next;
843 next = m->m_nextpkt;
844 continue;
845 }
846 if (m->m_len > len) {
847 m->m_len -= len;
848 m->m_data += len;
849 sb->sb_cc -= len;
850 if (m->m_type != MT_CONTROL && m->m_type != MT_SONAME)
851 sb->sb_datacc -= len;
852 break;
853 }
854 len -= m->m_len;
855 sbfree(sb, m);
856 MFREE(m, mn);
857 m = mn;
858 }
859 while (m && m->m_len == 0) {
860 sbfree(sb, m);
861 MFREE(m, mn);
862 m = mn;
863 }
864 if (m) {
865 sb->sb_mb = m;
866 m->m_nextpkt = next;
867 } else
868 sb->sb_mb = next;
869
870
871
872
873
874 m = sb->sb_mb;
875 if (m == NULL) {
876 sb->sb_mbtail = NULL;
877 sb->sb_lastrecord = NULL;
878 } else if (m->m_nextpkt == NULL)
879 sb->sb_lastrecord = m;
880 }
881
882
883
884
885
886 void
887 sbdroprecord(struct sockbuf *sb)
888 {
889 struct mbuf *m, *mn;
890
891 m = sb->sb_mb;
892 if (m) {
893 sb->sb_mb = m->m_nextpkt;
894 do {
895 sbfree(sb, m);
896 MFREE(m, mn);
897 } while ((m = mn) != NULL);
898 }
899 SB_EMPTY_FIXUP(sb);
900 }
901
902
903
904
905
906 struct mbuf *
907 sbcreatecontrol(caddr_t p, int size, int type, int level)
908 {
909 struct cmsghdr *cp;
910 struct mbuf *m;
911
912 if (CMSG_SPACE(size) > MCLBYTES) {
913 printf("sbcreatecontrol: message too large %d\n", size);
914 return NULL;
915 }
916
917 if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)
918 return ((struct mbuf *) NULL);
919 if (CMSG_SPACE(size) > MLEN) {
920 MCLGET(m, M_DONTWAIT);
921 if ((m->m_flags & M_EXT) == 0) {
922 m_free(m);
923 return NULL;
924 }
925 }
926 cp = mtod(m, struct cmsghdr *);
927 bcopy(p, CMSG_DATA(cp), size);
928 m->m_len = CMSG_SPACE(size);
929 cp->cmsg_len = CMSG_LEN(size);
930 cp->cmsg_level = level;
931 cp->cmsg_type = type;
932 return (m);
933 }