This source file includes following definitions.
- tcp6_usrreq
- tcp_usrreq
- tcp_ctloutput
- tcp_attach
- tcp_disconnect
- tcp_usrclosed
- tcp_ident
- tcp_sysctl
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/mbuf.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/protosw.h>
77 #include <sys/stat.h>
78 #include <sys/sysctl.h>
79 #include <sys/domain.h>
80 #include <sys/kernel.h>
81
82 #include <dev/rndvar.h>
83
84 #include <net/if.h>
85 #include <net/route.h>
86
87 #include <netinet/in.h>
88 #include <netinet/in_systm.h>
89 #include <netinet/in_var.h>
90 #include <netinet/ip.h>
91 #include <netinet/in_pcb.h>
92 #include <netinet/ip_var.h>
93 #include <netinet/tcp.h>
94 #include <netinet/tcp_fsm.h>
95 #include <netinet/tcp_seq.h>
96 #include <netinet/tcp_timer.h>
97 #include <netinet/tcp_var.h>
98 #include <netinet/tcpip.h>
99 #include <netinet/tcp_debug.h>
100
101
102
103
104 extern char *tcpstates[];
105 extern int tcptv_keep_init;
106
107 extern int tcp_rst_ppslim;
108
109
110 extern struct baddynamicports baddynamicports;
111
112 #ifndef TCP_SENDSPACE
113 #define TCP_SENDSPACE 1024*16
114 #endif
115 u_int tcp_sendspace = TCP_SENDSPACE;
116 #ifndef TCP_RECVSPACE
117 #define TCP_RECVSPACE 1024*16
118 #endif
119 u_int tcp_recvspace = TCP_RECVSPACE;
120
121 int *tcpctl_vars[TCPCTL_MAXID] = TCPCTL_VARS;
122
123 struct inpcbtable tcbtable;
124
125 int tcp_ident(void *, size_t *, void *, size_t, int);
126
127 #ifdef INET6
128 int
129 tcp6_usrreq(so, req, m, nam, control, p)
130 struct socket *so;
131 int req;
132 struct mbuf *m, *nam, *control;
133 struct proc *p;
134 {
135
136 return tcp_usrreq(so, req, m, nam, control);
137 }
138 #endif
139
140
141
142
143
144
145
146 int
147 tcp_usrreq(so, req, m, nam, control)
148 struct socket *so;
149 int req;
150 struct mbuf *m, *nam, *control;
151 {
152 struct sockaddr_in *sin;
153 struct inpcb *inp;
154 struct tcpcb *tp = NULL;
155 int s;
156 int error = 0;
157 short ostate;
158
159 if (req == PRU_CONTROL) {
160 #ifdef INET6
161 if (sotopf(so) == PF_INET6)
162 return in6_control(so, (u_long)m, (caddr_t)nam,
163 (struct ifnet *)control, 0);
164 else
165 #endif
166 return (in_control(so, (u_long)m, (caddr_t)nam,
167 (struct ifnet *)control));
168 }
169 if (control && control->m_len) {
170 m_freem(control);
171 if (m)
172 m_freem(m);
173 return (EINVAL);
174 }
175
176 s = splsoftnet();
177 inp = sotoinpcb(so);
178
179
180
181
182
183 if (inp == 0 && req != PRU_ATTACH) {
184 splx(s);
185
186
187
188
189 if (m && (req == PRU_SEND || req == PRU_SENDOOB))
190 m_freem(m);
191 return (EINVAL);
192 }
193 if (inp) {
194 tp = intotcpcb(inp);
195
196 #ifdef KPROF
197 tcp_acounts[tp->t_state][req]++;
198 #endif
199 ostate = tp->t_state;
200 } else
201 ostate = 0;
202 switch (req) {
203
204
205
206
207
208 case PRU_ATTACH:
209 if (inp) {
210 error = EISCONN;
211 break;
212 }
213 error = tcp_attach(so);
214 if (error)
215 break;
216 if ((so->so_options & SO_LINGER) && so->so_linger == 0)
217 so->so_linger = TCP_LINGERTIME;
218 tp = sototcpcb(so);
219 break;
220
221
222
223
224
225
226
227
228 case PRU_DETACH:
229 tp = tcp_disconnect(tp);
230 break;
231
232
233
234
235 case PRU_BIND:
236 #ifdef INET6
237 if (inp->inp_flags & INP_IPV6)
238 error = in6_pcbbind(inp, nam);
239 else
240 #endif
241 error = in_pcbbind(inp, nam);
242 if (error)
243 break;
244 break;
245
246
247
248
249 case PRU_LISTEN:
250 if (inp->inp_lport == 0) {
251 #ifdef INET6
252 if (inp->inp_flags & INP_IPV6)
253 error = in6_pcbbind(inp, NULL);
254 else
255 #endif
256 error = in_pcbbind(inp, NULL);
257 }
258
259
260 if (error == 0)
261 tp->t_state = TCPS_LISTEN;
262 break;
263
264
265
266
267
268
269
270
271 case PRU_CONNECT:
272 sin = mtod(nam, struct sockaddr_in *);
273
274 #ifdef INET6
275 if (sin->sin_family == AF_INET6) {
276 struct in6_addr *in6_addr = &mtod(nam,
277 struct sockaddr_in6 *)->sin6_addr;
278
279 if (IN6_IS_ADDR_UNSPECIFIED(in6_addr) ||
280 IN6_IS_ADDR_MULTICAST(in6_addr) ||
281 (IN6_IS_ADDR_V4MAPPED(in6_addr) &&
282 ((in6_addr->s6_addr32[3] == INADDR_ANY) ||
283 IN_MULTICAST(in6_addr->s6_addr32[3]) ||
284 in_broadcast(sin->sin_addr, NULL)))) {
285 error = EINVAL;
286 break;
287 }
288
289 if (inp->inp_lport == 0) {
290 error = in6_pcbbind(inp, NULL);
291 if (error)
292 break;
293 }
294 error = in6_pcbconnect(inp, nam);
295 } else if (sin->sin_family == AF_INET)
296 #endif
297 {
298 if ((sin->sin_addr.s_addr == INADDR_ANY) ||
299 IN_MULTICAST(sin->sin_addr.s_addr) ||
300 in_broadcast(sin->sin_addr, NULL)) {
301 error = EINVAL;
302 break;
303 }
304
305 if (inp->inp_lport == 0) {
306 error = in_pcbbind(inp, NULL);
307 if (error)
308 break;
309 }
310 error = in_pcbconnect(inp, nam);
311 }
312
313 if (error)
314 break;
315
316 tp->t_template = tcp_template(tp);
317 if (tp->t_template == 0) {
318 in_pcbdisconnect(inp);
319 error = ENOBUFS;
320 break;
321 }
322
323 so->so_state |= SS_CONNECTOUT;
324
325
326 tcp_rscale(tp, so->so_rcv.sb_hiwat);
327
328 soisconnecting(so);
329 tcpstat.tcps_connattempt++;
330 tp->t_state = TCPS_SYN_SENT;
331 TCP_TIMER_ARM(tp, TCPT_KEEP, tcptv_keep_init);
332 #ifdef TCP_COMPAT_42
333 tp->iss = tcp_iss;
334 tcp_iss += TCP_ISSINCR/2;
335 #else
336 tcp_set_iss_tsm(tp);
337 #endif
338 tcp_sendseqinit(tp);
339 #if defined(TCP_SACK)
340 tp->snd_last = tp->snd_una;
341 #endif
342 #if defined(TCP_SACK) && defined(TCP_FACK)
343 tp->snd_fack = tp->snd_una;
344 tp->retran_data = 0;
345 tp->snd_awnd = 0;
346 #endif
347 error = tcp_output(tp);
348 break;
349
350
351
352
353 case PRU_CONNECT2:
354 error = EOPNOTSUPP;
355 break;
356
357
358
359
360
361
362
363
364
365
366
367
368 case PRU_DISCONNECT:
369 tp = tcp_disconnect(tp);
370 break;
371
372
373
374
375
376
377 case PRU_ACCEPT:
378 #ifdef INET6
379 if (inp->inp_flags & INP_IPV6)
380 in6_setpeeraddr(inp, nam);
381 else
382 #endif
383 in_setpeeraddr(inp, nam);
384 break;
385
386
387
388
389 case PRU_SHUTDOWN:
390 if (so->so_state & SS_CANTSENDMORE)
391 break;
392 socantsendmore(so);
393 tp = tcp_usrclosed(tp);
394 if (tp)
395 error = tcp_output(tp);
396 break;
397
398
399
400
401 case PRU_RCVD:
402
403
404
405
406
407
408
409 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) != 0)
410 (void) tcp_output(tp);
411 break;
412
413
414
415
416
417 case PRU_SEND:
418 sbappendstream(&so->so_snd, m);
419 error = tcp_output(tp);
420 break;
421
422
423
424
425 case PRU_ABORT:
426 tp = tcp_drop(tp, ECONNABORTED);
427 break;
428
429 case PRU_SENSE:
430 ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
431 splx(s);
432 return (0);
433
434 case PRU_RCVOOB:
435 if ((so->so_oobmark == 0 &&
436 (so->so_state & SS_RCVATMARK) == 0) ||
437 so->so_options & SO_OOBINLINE ||
438 tp->t_oobflags & TCPOOB_HADDATA) {
439 error = EINVAL;
440 break;
441 }
442 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
443 error = EWOULDBLOCK;
444 break;
445 }
446 m->m_len = 1;
447 *mtod(m, caddr_t) = tp->t_iobc;
448 if (((long)nam & MSG_PEEK) == 0)
449 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
450 break;
451
452 case PRU_SENDOOB:
453 if (sbspace(&so->so_snd) < -512) {
454 m_freem(m);
455 error = ENOBUFS;
456 break;
457 }
458
459
460
461
462
463
464
465
466 sbappendstream(&so->so_snd, m);
467 tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
468 tp->t_force = 1;
469 error = tcp_output(tp);
470 tp->t_force = 0;
471 break;
472
473 case PRU_SOCKADDR:
474 #ifdef INET6
475 if (inp->inp_flags & INP_IPV6)
476 in6_setsockaddr(inp, nam);
477 else
478 #endif
479 in_setsockaddr(inp, nam);
480 break;
481
482 case PRU_PEERADDR:
483 #ifdef INET6
484 if (inp->inp_flags & INP_IPV6)
485 in6_setpeeraddr(inp, nam);
486 else
487 #endif
488 in_setpeeraddr(inp, nam);
489 break;
490
491 default:
492 panic("tcp_usrreq");
493 }
494 if (tp && (so->so_options & SO_DEBUG))
495 tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0);
496 splx(s);
497 return (error);
498 }
499
500 int
501 tcp_ctloutput(op, so, level, optname, mp)
502 int op;
503 struct socket *so;
504 int level, optname;
505 struct mbuf **mp;
506 {
507 int error = 0, s;
508 struct inpcb *inp;
509 struct tcpcb *tp;
510 struct mbuf *m;
511 int i;
512
513 s = splsoftnet();
514 inp = sotoinpcb(so);
515 if (inp == NULL) {
516 splx(s);
517 if (op == PRCO_SETOPT && *mp)
518 (void) m_free(*mp);
519 return (ECONNRESET);
520 }
521 #ifdef INET6
522 tp = intotcpcb(inp);
523 #endif
524 if (level != IPPROTO_TCP) {
525 switch (so->so_proto->pr_domain->dom_family) {
526 #ifdef INET6
527 case PF_INET6:
528 error = ip6_ctloutput(op, so, level, optname, mp);
529 break;
530 #endif
531 case PF_INET:
532 error = ip_ctloutput(op, so, level, optname, mp);
533 break;
534 default:
535 error = EAFNOSUPPORT;
536 break;
537 }
538 splx(s);
539 return (error);
540 }
541 #ifndef INET6
542 tp = intotcpcb(inp);
543 #endif
544
545 switch (op) {
546
547 case PRCO_SETOPT:
548 m = *mp;
549 switch (optname) {
550
551 case TCP_NODELAY:
552 if (m == NULL || m->m_len < sizeof (int))
553 error = EINVAL;
554 else if (*mtod(m, int *))
555 tp->t_flags |= TF_NODELAY;
556 else
557 tp->t_flags &= ~TF_NODELAY;
558 break;
559
560 case TCP_MAXSEG:
561 if (m == NULL || m->m_len < sizeof (int)) {
562 error = EINVAL;
563 break;
564 }
565
566 i = *mtod(m, int *);
567 if (i > 0 && i <= tp->t_maxseg)
568 tp->t_maxseg = i;
569 else
570 error = EINVAL;
571 break;
572
573 #ifdef TCP_SACK
574 case TCP_SACK_ENABLE:
575 if (m == NULL || m->m_len < sizeof (int)) {
576 error = EINVAL;
577 break;
578 }
579
580 if (TCPS_HAVEESTABLISHED(tp->t_state)) {
581 error = EPERM;
582 break;
583 }
584
585 if (tp->t_flags & TF_SIGNATURE) {
586 error = EPERM;
587 break;
588 }
589
590 if (*mtod(m, int *))
591 tp->sack_enable = 1;
592 else
593 tp->sack_enable = 0;
594 break;
595 #endif
596 #ifdef TCP_SIGNATURE
597 case TCP_MD5SIG:
598 if (m == NULL || m->m_len < sizeof (int)) {
599 error = EINVAL;
600 break;
601 }
602
603 if (TCPS_HAVEESTABLISHED(tp->t_state)) {
604 error = EPERM;
605 break;
606 }
607
608 if (*mtod(m, int *)) {
609 tp->t_flags |= TF_SIGNATURE;
610 #ifdef TCP_SACK
611 tp->sack_enable = 0;
612 #endif
613 } else
614 tp->t_flags &= ~TF_SIGNATURE;
615 break;
616 #endif
617 default:
618 error = ENOPROTOOPT;
619 break;
620 }
621 if (m)
622 (void) m_free(m);
623 break;
624
625 case PRCO_GETOPT:
626 *mp = m = m_get(M_WAIT, MT_SOOPTS);
627 m->m_len = sizeof(int);
628
629 switch (optname) {
630 case TCP_NODELAY:
631 *mtod(m, int *) = tp->t_flags & TF_NODELAY;
632 break;
633 case TCP_MAXSEG:
634 *mtod(m, int *) = tp->t_maxseg;
635 break;
636 #ifdef TCP_SACK
637 case TCP_SACK_ENABLE:
638 *mtod(m, int *) = tp->sack_enable;
639 break;
640 #endif
641 #ifdef TCP_SIGNATURE
642 case TCP_MD5SIG:
643 *mtod(m, int *) = tp->t_flags & TF_SIGNATURE;
644 break;
645 #endif
646 default:
647 error = ENOPROTOOPT;
648 break;
649 }
650 break;
651 }
652 splx(s);
653 return (error);
654 }
655
656
657
658
659
660
661 int
662 tcp_attach(so)
663 struct socket *so;
664 {
665 struct tcpcb *tp;
666 struct inpcb *inp;
667 int error;
668
669 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
670 error = soreserve(so, tcp_sendspace, tcp_recvspace);
671 if (error)
672 return (error);
673 }
674 error = in_pcballoc(so, &tcbtable);
675 if (error)
676 return (error);
677 inp = sotoinpcb(so);
678 tp = tcp_newtcpcb(inp);
679 if (tp == NULL) {
680 int nofd = so->so_state & SS_NOFDREF;
681
682 so->so_state &= ~SS_NOFDREF;
683 in_pcbdetach(inp);
684 so->so_state |= nofd;
685 return (ENOBUFS);
686 }
687 tp->t_state = TCPS_CLOSED;
688 #ifdef INET6
689
690 if (inp->inp_flags & INP_IPV6)
691 tp->pf = PF_INET6;
692 else
693 tp->pf = PF_INET;
694 #else
695 tp->pf = PF_INET;
696 #endif
697 return (0);
698 }
699
700
701
702
703
704
705
706
707
708 struct tcpcb *
709 tcp_disconnect(tp)
710 struct tcpcb *tp;
711 {
712 struct socket *so = tp->t_inpcb->inp_socket;
713
714 if (TCPS_HAVEESTABLISHED(tp->t_state) == 0)
715 tp = tcp_close(tp);
716 else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
717 tp = tcp_drop(tp, 0);
718 else {
719 soisdisconnecting(so);
720 sbflush(&so->so_rcv);
721 tp = tcp_usrclosed(tp);
722 if (tp)
723 (void) tcp_output(tp);
724 }
725 return (tp);
726 }
727
728
729
730
731
732
733
734
735
736
737
738 struct tcpcb *
739 tcp_usrclosed(tp)
740 struct tcpcb *tp;
741 {
742
743 switch (tp->t_state) {
744
745 case TCPS_CLOSED:
746 case TCPS_LISTEN:
747 case TCPS_SYN_SENT:
748 tp->t_state = TCPS_CLOSED;
749 tp = tcp_close(tp);
750 break;
751
752 case TCPS_SYN_RECEIVED:
753 case TCPS_ESTABLISHED:
754 tp->t_state = TCPS_FIN_WAIT_1;
755 break;
756
757 case TCPS_CLOSE_WAIT:
758 tp->t_state = TCPS_LAST_ACK;
759 break;
760 }
761 if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {
762 soisdisconnected(tp->t_inpcb->inp_socket);
763
764
765
766
767
768
769
770 if (tp->t_state == TCPS_FIN_WAIT_2)
771 TCP_TIMER_ARM(tp, TCPT_2MSL, tcp_maxidle);
772 }
773 return (tp);
774 }
775
776
777
778
779 int
780 tcp_ident(oldp, oldlenp, newp, newlen, dodrop)
781 void *oldp;
782 size_t *oldlenp;
783 void *newp;
784 size_t newlen;
785 int dodrop;
786 {
787 int error = 0, s;
788 struct tcp_ident_mapping tir;
789 struct inpcb *inp;
790 struct tcpcb *tp = NULL;
791 struct sockaddr_in *fin, *lin;
792 #ifdef INET6
793 struct sockaddr_in6 *fin6, *lin6;
794 struct in6_addr f6, l6;
795 #endif
796 if (dodrop) {
797 if (oldp != NULL || *oldlenp != 0)
798 return (EINVAL);
799 if (newp == NULL)
800 return (EPERM);
801 if (newlen < sizeof(tir))
802 return (ENOMEM);
803 if ((error = copyin(newp, &tir, sizeof (tir))) != 0 )
804 return (error);
805 } else {
806 if (oldp == NULL)
807 return (EINVAL);
808 if (*oldlenp < sizeof(tir))
809 return (ENOMEM);
810 if (newp != NULL || newlen != 0)
811 return (EINVAL);
812 if ((error = copyin(oldp, &tir, sizeof (tir))) != 0 )
813 return (error);
814 }
815 switch (tir.faddr.ss_family) {
816 #ifdef INET6
817 case AF_INET6:
818 fin6 = (struct sockaddr_in6 *)&tir.faddr;
819 error = in6_embedscope(&f6, fin6, NULL, NULL);
820 if (error)
821 return EINVAL;
822 lin6 = (struct sockaddr_in6 *)&tir.laddr;
823 error = in6_embedscope(&l6, lin6, NULL, NULL);
824 if (error)
825 return EINVAL;
826 break;
827 #endif
828 case AF_INET:
829 fin = (struct sockaddr_in *)&tir.faddr;
830 lin = (struct sockaddr_in *)&tir.laddr;
831 break;
832 default:
833 return (EINVAL);
834 }
835
836 s = splsoftnet();
837 switch (tir.faddr.ss_family) {
838 #ifdef INET6
839 case AF_INET6:
840 inp = in6_pcbhashlookup(&tcbtable, &f6,
841 fin6->sin6_port, &l6, lin6->sin6_port);
842 break;
843 #endif
844 case AF_INET:
845 inp = in_pcbhashlookup(&tcbtable, fin->sin_addr,
846 fin->sin_port, lin->sin_addr, lin->sin_port);
847 break;
848 }
849
850 if (dodrop) {
851 if (inp && (tp = intotcpcb(inp)) &&
852 ((inp->inp_socket->so_options & SO_ACCEPTCONN) == 0))
853 tp = tcp_drop(tp, ECONNABORTED);
854 else
855 error = ESRCH;
856 splx(s);
857 return (error);
858 }
859
860 if (inp == NULL) {
861 ++tcpstat.tcps_pcbhashmiss;
862 switch (tir.faddr.ss_family) {
863 #ifdef INET6
864 case AF_INET6:
865 inp = in6_pcblookup_listen(&tcbtable,
866 &l6, lin6->sin6_port, 0);
867 break;
868 #endif
869 case AF_INET:
870 inp = in_pcblookup_listen(&tcbtable,
871 lin->sin_addr, lin->sin_port, 0);
872 break;
873 }
874 }
875
876 if (inp != NULL && (inp->inp_socket->so_state & SS_CONNECTOUT)) {
877 tir.ruid = inp->inp_socket->so_ruid;
878 tir.euid = inp->inp_socket->so_euid;
879 } else {
880 tir.ruid = -1;
881 tir.euid = -1;
882 }
883 splx(s);
884
885 *oldlenp = sizeof (tir);
886 error = copyout((void *)&tir, oldp, sizeof (tir));
887 return (error);
888 }
889
890
891
892
893 int
894 tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
895 int *name;
896 u_int namelen;
897 void *oldp;
898 size_t *oldlenp;
899 void *newp;
900 size_t newlen;
901 {
902 int error, nval;
903
904
905 if (namelen != 1)
906 return (ENOTDIR);
907
908 switch (name[0]) {
909 #ifdef TCP_SACK
910 case TCPCTL_SACK:
911 return (sysctl_int(oldp, oldlenp, newp, newlen,
912 &tcp_do_sack));
913 #endif
914 case TCPCTL_SLOWHZ:
915 return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));
916
917 case TCPCTL_BADDYNAMIC:
918 return (sysctl_struct(oldp, oldlenp, newp, newlen,
919 baddynamicports.tcp, sizeof(baddynamicports.tcp)));
920
921 case TCPCTL_IDENT:
922 return (tcp_ident(oldp, oldlenp, newp, newlen, 0));
923
924 case TCPCTL_DROP:
925 return (tcp_ident(oldp, oldlenp, newp, newlen, 1));
926
927 #ifdef TCP_ECN
928 case TCPCTL_ECN:
929 return (sysctl_int(oldp, oldlenp, newp, newlen,
930 &tcp_do_ecn));
931 #endif
932 case TCPCTL_REASS_LIMIT:
933 nval = tcp_reass_limit;
934 error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
935 if (error)
936 return (error);
937 if (nval != tcp_reass_limit) {
938 error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
939 if (error)
940 return (error);
941 tcp_reass_limit = nval;
942 }
943 return (0);
944 #ifdef TCP_SACK
945 case TCPCTL_SACKHOLE_LIMIT:
946 nval = tcp_sackhole_limit;
947 error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
948 if (error)
949 return (error);
950 if (nval != tcp_sackhole_limit) {
951 error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
952 if (error)
953 return (error);
954 tcp_sackhole_limit = nval;
955 }
956 return (0);
957 #endif
958 default:
959 if (name[0] < TCPCTL_MAXID)
960 return (sysctl_int_arr(tcpctl_vars, name, namelen,
961 oldp, oldlenp, newp, newlen));
962 return (ENOPROTOOPT);
963 }
964
965 }