| @@ -1,35 +1,35 @@ | | | @@ -1,35 +1,35 @@ |
1 | /* $NetBSD: if_tun.c,v 1.157 2019/12/13 14:13:55 maxv Exp $ */ | | 1 | /* $NetBSD: if_tun.c,v 1.158 2020/01/29 04:34:10 thorpej Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> | | 4 | * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> |
5 | * Nottingham University 1987. | | 5 | * Nottingham University 1987. |
6 | * | | 6 | * |
7 | * This source may be freely distributed, however I would be interested | | 7 | * This source may be freely distributed, however I would be interested |
8 | * in any changes that are made. | | 8 | * in any changes that are made. |
9 | * | | 9 | * |
10 | * This driver takes packets off the IP i/f and hands them up to a | | 10 | * This driver takes packets off the IP i/f and hands them up to a |
11 | * user process to have its wicked way with. This driver has its | | 11 | * user process to have its wicked way with. This driver has its |
12 | * roots in a similar driver written by Phil Cockcroft (formerly) at | | 12 | * roots in a similar driver written by Phil Cockcroft (formerly) at |
13 | * UCL. This driver is based much more on read/write/poll mode of | | 13 | * UCL. This driver is based much more on read/write/poll mode of |
14 | * operation though. | | 14 | * operation though. |
15 | */ | | 15 | */ |
16 | | | 16 | |
17 | /* | | 17 | /* |
18 | * tun - tunnel software network interface. | | 18 | * tun - tunnel software network interface. |
19 | */ | | 19 | */ |
20 | | | 20 | |
21 | #include <sys/cdefs.h> | | 21 | #include <sys/cdefs.h> |
22 | __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.157 2019/12/13 14:13:55 maxv Exp $"); | | 22 | __KERNEL_RCSID(0, "$NetBSD: if_tun.c,v 1.158 2020/01/29 04:34:10 thorpej Exp $"); |
23 | | | 23 | |
24 | #ifdef _KERNEL_OPT | | 24 | #ifdef _KERNEL_OPT |
25 | #include "opt_inet.h" | | 25 | #include "opt_inet.h" |
26 | #endif | | 26 | #endif |
27 | | | 27 | |
28 | #include <sys/param.h> | | 28 | #include <sys/param.h> |
29 | | | 29 | |
30 | #include <sys/buf.h> | | 30 | #include <sys/buf.h> |
31 | #include <sys/conf.h> | | 31 | #include <sys/conf.h> |
32 | #include <sys/cpu.h> | | 32 | #include <sys/cpu.h> |
33 | #include <sys/device.h> | | 33 | #include <sys/device.h> |
34 | #include <sys/file.h> | | 34 | #include <sys/file.h> |
35 | #include <sys/ioctl.h> | | 35 | #include <sys/ioctl.h> |
| @@ -249,33 +249,26 @@ tunattach0(struct tun_softc *tp) | | | @@ -249,33 +249,26 @@ tunattach0(struct tun_softc *tp) |
249 | | | 249 | |
250 | ifp = &tp->tun_if; | | 250 | ifp = &tp->tun_if; |
251 | ifp->if_softc = tp; | | 251 | ifp->if_softc = tp; |
252 | ifp->if_mtu = TUNMTU; | | 252 | ifp->if_mtu = TUNMTU; |
253 | ifp->if_ioctl = tun_ioctl; | | 253 | ifp->if_ioctl = tun_ioctl; |
254 | ifp->if_output = tun_output; | | 254 | ifp->if_output = tun_output; |
255 | #ifdef ALTQ | | 255 | #ifdef ALTQ |
256 | ifp->if_start = tunstart; | | 256 | ifp->if_start = tunstart; |
257 | #endif | | 257 | #endif |
258 | ifp->if_flags = IFF_POINTOPOINT; | | 258 | ifp->if_flags = IFF_POINTOPOINT; |
259 | ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE; | | 259 | ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE; |
260 | ifp->if_type = IFT_TUNNEL; | | 260 | ifp->if_type = IFT_TUNNEL; |
261 | ifp->if_snd.ifq_maxlen = ifqmaxlen; | | 261 | ifp->if_snd.ifq_maxlen = ifqmaxlen; |
262 | ifp->if_collisions = 0; | | | |
263 | ifp->if_ierrors = 0; | | | |
264 | ifp->if_oerrors = 0; | | | |
265 | ifp->if_ipackets = 0; | | | |
266 | ifp->if_opackets = 0; | | | |
267 | ifp->if_ibytes = 0; | | | |
268 | ifp->if_obytes = 0; | | | |
269 | ifp->if_dlt = DLT_NULL; | | 262 | ifp->if_dlt = DLT_NULL; |
270 | IFQ_SET_READY(&ifp->if_snd); | | 263 | IFQ_SET_READY(&ifp->if_snd); |
271 | if_attach(ifp); | | 264 | if_attach(ifp); |
272 | if_alloc_sadl(ifp); | | 265 | if_alloc_sadl(ifp); |
273 | bpf_attach(ifp, DLT_NULL, sizeof(uint32_t)); | | 266 | bpf_attach(ifp, DLT_NULL, sizeof(uint32_t)); |
274 | } | | 267 | } |
275 | | | 268 | |
276 | static int | | 269 | static int |
277 | tun_clone_destroy(struct ifnet *ifp) | | 270 | tun_clone_destroy(struct ifnet *ifp) |
278 | { | | 271 | { |
279 | struct tun_softc *tp = (void *)ifp; | | 272 | struct tun_softc *tp = (void *)ifp; |
280 | bool zombie = false; | | 273 | bool zombie = false; |
281 | | | 274 | |
| @@ -602,33 +595,32 @@ tun_output(struct ifnet *ifp, struct mbu | | | @@ -602,33 +595,32 @@ tun_output(struct ifnet *ifp, struct mbu |
602 | #ifdef INET | | 595 | #ifdef INET |
603 | if (dst->sa_family != AF_INET) | | 596 | if (dst->sa_family != AF_INET) |
604 | #endif | | 597 | #endif |
605 | { | | 598 | { |
606 | error = EAFNOSUPPORT; | | 599 | error = EAFNOSUPPORT; |
607 | goto out; | | 600 | goto out; |
608 | } | | 601 | } |
609 | } | | 602 | } |
610 | /* FALLTHROUGH */ | | 603 | /* FALLTHROUGH */ |
611 | case AF_UNSPEC: | | 604 | case AF_UNSPEC: |
612 | mlen = m0->m_pkthdr.len; | | 605 | mlen = m0->m_pkthdr.len; |
613 | IFQ_ENQUEUE(&ifp->if_snd, m0, error); | | 606 | IFQ_ENQUEUE(&ifp->if_snd, m0, error); |
614 | if (error) { | | 607 | if (error) { |
615 | ifp->if_collisions++; | | 608 | if_statinc(ifp, if_collisions); |
616 | error = EAFNOSUPPORT; | | 609 | error = EAFNOSUPPORT; |
617 | m0 = NULL; | | 610 | m0 = NULL; |
618 | goto out; | | 611 | goto out; |
619 | } | | 612 | } |
620 | ifp->if_opackets++; | | 613 | if_statadd2(ifp, if_opackets, 1, if_obytes, mlen); |
621 | ifp->if_obytes += mlen; | | | |
622 | break; | | 614 | break; |
623 | #endif | | 615 | #endif |
624 | default: | | 616 | default: |
625 | error = EAFNOSUPPORT; | | 617 | error = EAFNOSUPPORT; |
626 | goto out; | | 618 | goto out; |
627 | } | | 619 | } |
628 | | | 620 | |
629 | mutex_enter(&tp->tun_lock); | | 621 | mutex_enter(&tp->tun_lock); |
630 | if (tp->tun_flags & TUN_RWAIT) { | | 622 | if (tp->tun_flags & TUN_RWAIT) { |
631 | tp->tun_flags &= ~TUN_RWAIT; | | 623 | tp->tun_flags &= ~TUN_RWAIT; |
632 | cv_broadcast(&tp->tun_cv); | | 624 | cv_broadcast(&tp->tun_cv); |
633 | } | | 625 | } |
634 | if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) | | 626 | if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid) |
| @@ -818,27 +810,27 @@ tunread(dev_t dev, struct uio *uio, int | | | @@ -818,27 +810,27 @@ tunread(dev_t dev, struct uio *uio, int |
818 | /* Copy the mbuf chain */ | | 810 | /* Copy the mbuf chain */ |
819 | while (m0 && uio->uio_resid > 0 && error == 0) { | | 811 | while (m0 && uio->uio_resid > 0 && error == 0) { |
820 | len = uimin(uio->uio_resid, m0->m_len); | | 812 | len = uimin(uio->uio_resid, m0->m_len); |
821 | if (len != 0) | | 813 | if (len != 0) |
822 | error = uiomove(mtod(m0, void *), len, uio); | | 814 | error = uiomove(mtod(m0, void *), len, uio); |
823 | m0 = m = m_free(m0); | | 815 | m0 = m = m_free(m0); |
824 | } | | 816 | } |
825 | | | 817 | |
826 | if (m0) { | | 818 | if (m0) { |
827 | TUNDEBUG("Dropping mbuf\n"); | | 819 | TUNDEBUG("Dropping mbuf\n"); |
828 | m_freem(m0); | | 820 | m_freem(m0); |
829 | } | | 821 | } |
830 | if (error) | | 822 | if (error) |
831 | ifp->if_ierrors++; | | 823 | if_statinc(ifp, if_ierrors); |
832 | | | 824 | |
833 | return error; | | 825 | return error; |
834 | | | 826 | |
835 | out: | | 827 | out: |
836 | mutex_exit(&tp->tun_lock); | | 828 | mutex_exit(&tp->tun_lock); |
837 | | | 829 | |
838 | return error; | | 830 | return error; |
839 | } | | 831 | } |
840 | | | 832 | |
841 | /* | | 833 | /* |
842 | * the cdevsw write interface - an atomic write is a packet - or else! | | 834 | * the cdevsw write interface - an atomic write is a packet - or else! |
843 | */ | | 835 | */ |
844 | int | | 836 | int |
| @@ -936,55 +928,54 @@ tunwrite(dev_t dev, struct uio *uio, int | | | @@ -936,55 +928,54 @@ tunwrite(dev_t dev, struct uio *uio, int |
936 | mp = &m->m_next; | | 928 | mp = &m->m_next; |
937 | if (error == 0 && uio->uio_resid > 0) { | | 929 | if (error == 0 && uio->uio_resid > 0) { |
938 | MGET(m, M_DONTWAIT, MT_DATA); | | 930 | MGET(m, M_DONTWAIT, MT_DATA); |
939 | if (m == NULL) { | | 931 | if (m == NULL) { |
940 | error = ENOBUFS; | | 932 | error = ENOBUFS; |
941 | break; | | 933 | break; |
942 | } | | 934 | } |
943 | mlen = MLEN; | | 935 | mlen = MLEN; |
944 | } | | 936 | } |
945 | } | | 937 | } |
946 | if (error) { | | 938 | if (error) { |
947 | if (top != NULL) | | 939 | if (top != NULL) |
948 | m_freem(top); | | 940 | m_freem(top); |
949 | ifp->if_ierrors++; | | 941 | if_statinc(ifp, if_ierrors); |
950 | goto out0; | | 942 | goto out0; |
951 | } | | 943 | } |
952 | | | 944 | |
953 | top->m_pkthdr.len = tlen; | | 945 | top->m_pkthdr.len = tlen; |
954 | m_set_rcvif(top, ifp); | | 946 | m_set_rcvif(top, ifp); |
955 | | | 947 | |
956 | bpf_mtap_af(ifp, dst.sa_family, top, BPF_D_IN); | | 948 | bpf_mtap_af(ifp, dst.sa_family, top, BPF_D_IN); |
957 | | | 949 | |
958 | if ((error = pfil_run_hooks(ifp->if_pfil, &top, ifp, PFIL_IN)) != 0) | | 950 | if ((error = pfil_run_hooks(ifp->if_pfil, &top, ifp, PFIL_IN)) != 0) |
959 | goto out0; | | 951 | goto out0; |
960 | if (top == NULL) | | 952 | if (top == NULL) |
961 | goto out0; | | 953 | goto out0; |
962 | | | 954 | |
963 | mutex_enter(&tp->tun_lock); | | 955 | mutex_enter(&tp->tun_lock); |
964 | if ((tp->tun_flags & TUN_INITED) == 0) { | | 956 | if ((tp->tun_flags & TUN_INITED) == 0) { |
965 | /* Interface was destroyed */ | | 957 | /* Interface was destroyed */ |
966 | error = ENXIO; | | 958 | error = ENXIO; |
967 | goto out; | | 959 | goto out; |
968 | } | | 960 | } |
969 | if (__predict_false(!pktq_enqueue(pktq, top, 0))) { | | 961 | if (__predict_false(!pktq_enqueue(pktq, top, 0))) { |
970 | ifp->if_collisions++; | | 962 | if_statinc(ifp, if_collisions); |
971 | mutex_exit(&tp->tun_lock); | | 963 | mutex_exit(&tp->tun_lock); |
972 | error = ENOBUFS; | | 964 | error = ENOBUFS; |
973 | m_freem(top); | | 965 | m_freem(top); |
974 | goto out0; | | 966 | goto out0; |
975 | } | | 967 | } |
976 | ifp->if_ipackets++; | | 968 | if_statadd2(ifp, if_ipackets, 1, if_ibytes, tlen); |
977 | ifp->if_ibytes += tlen; | | | |
978 | out: | | 969 | out: |
979 | mutex_exit(&tp->tun_lock); | | 970 | mutex_exit(&tp->tun_lock); |
980 | out0: | | 971 | out0: |
981 | return error; | | 972 | return error; |
982 | } | | 973 | } |
983 | | | 974 | |
984 | #ifdef ALTQ | | 975 | #ifdef ALTQ |
985 | /* | | 976 | /* |
986 | * Start packet transmission on the interface. | | 977 | * Start packet transmission on the interface. |
987 | * when the interface queue is rate-limited by ALTQ or TBR, | | 978 | * when the interface queue is rate-limited by ALTQ or TBR, |
988 | * if_start is needed to drain packets from the queue in order | | 979 | * if_start is needed to drain packets from the queue in order |
989 | * to notify readers when outgoing packets become ready. | | 980 | * to notify readers when outgoing packets become ready. |
990 | */ | | 981 | */ |