| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: natm.c,v 1.24 2011/03/09 22:06:42 dyoung Exp $ */ | | 1 | /* $NetBSD: natm.c,v 1.24.28.1 2014/08/10 06:56:41 tls Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996 Charles D. Cranor and Washington University. | | 4 | * Copyright (c) 1996 Charles D. Cranor and Washington University. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -20,313 +20,480 @@ | | | @@ -20,313 +20,480 @@ |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | /* | | 28 | /* |
29 | * natm.c: native mode ATM access (both aal0 and aal5). | | 29 | * natm.c: native mode ATM access (both aal0 and aal5). |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.24 2011/03/09 22:06:42 dyoung Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.24.28.1 2014/08/10 06:56:41 tls Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
| | | 36 | #include <sys/kmem.h> |
36 | #include <sys/systm.h> | | 37 | #include <sys/systm.h> |
37 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
38 | #include <sys/domain.h> | | 39 | #include <sys/domain.h> |
39 | #include <sys/ioctl.h> | | 40 | #include <sys/ioctl.h> |
40 | #include <sys/proc.h> | | | |
41 | #include <sys/protosw.h> | | 41 | #include <sys/protosw.h> |
42 | #include <sys/mbuf.h> | | 42 | #include <sys/mbuf.h> |
43 | #include <sys/socket.h> | | 43 | #include <sys/socket.h> |
44 | #include <sys/socketvar.h> | | 44 | #include <sys/socketvar.h> |
45 | | | 45 | |
46 | #include <net/if.h> | | 46 | #include <net/if.h> |
47 | #include <net/if_atm.h> | | 47 | #include <net/if_atm.h> |
48 | #include <net/netisr.h> | | 48 | #include <net/netisr.h> |
49 | #include <net/radix.h> | | | |
50 | #include <net/route.h> | | 49 | #include <net/route.h> |
51 | | | 50 | |
52 | #include <netinet/in.h> | | 51 | #include <netinet/in.h> |
53 | | | 52 | |
54 | #include <netnatm/natm.h> | | 53 | #include <netnatm/natm.h> |
55 | | | 54 | |
56 | u_long natm5_sendspace = 16*1024; | | 55 | u_long natm5_sendspace = 16*1024; |
57 | u_long natm5_recvspace = 16*1024; | | 56 | u_long natm5_recvspace = 16*1024; |
58 | | | 57 | |
59 | u_long natm0_sendspace = 16*1024; | | 58 | u_long natm0_sendspace = 16*1024; |
60 | u_long natm0_recvspace = 16*1024; | | 59 | u_long natm0_recvspace = 16*1024; |
61 | | | 60 | |
62 | /* | | 61 | static int |
63 | * user requests | | 62 | natm_attach(struct socket *so, int proto) |
64 | */ | | 63 | { |
| | | 64 | int error = 0; |
| | | 65 | struct natmpcb *npcb; |
65 | | | 66 | |
66 | int natm_usrreq(so, req, m, nam, control, l) | | 67 | KASSERT(so->so_pcb == NULL); |
| | | 68 | sosetlock(so); |
67 | | | 69 | |
68 | struct socket *so; | | 70 | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { |
69 | int req; | | 71 | if (proto == PROTO_NATMAAL5) |
70 | struct mbuf *m, *nam, *control; | | 72 | error = soreserve(so, natm5_sendspace, natm5_recvspace); |
71 | struct lwp *l; | | 73 | else |
| | | 74 | error = soreserve(so, natm0_sendspace, natm0_recvspace); |
| | | 75 | if (error) |
| | | 76 | return error; |
| | | 77 | } |
| | | 78 | npcb = npcb_alloc(true); |
| | | 79 | npcb->npcb_socket = so; |
| | | 80 | so->so_pcb = npcb; |
| | | 81 | return error; |
| | | 82 | } |
72 | | | 83 | |
| | | 84 | static void |
| | | 85 | natm_detach(struct socket *so) |
73 | { | | 86 | { |
74 | int error = 0, s, s2; | | 87 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; |
| | | 88 | |
| | | 89 | /* |
| | | 90 | * we turn on 'drain' *before* we sofree. |
| | | 91 | */ |
| | | 92 | |
| | | 93 | npcb_free(npcb, NPCB_DESTROY); /* drain */ |
| | | 94 | so->so_pcb = NULL; |
| | | 95 | /* sofree drops the lock */ |
| | | 96 | sofree(so); |
| | | 97 | mutex_enter(softnet_lock); |
| | | 98 | } |
| | | 99 | |
| | | 100 | static int |
| | | 101 | natm_accept(struct socket *so, struct mbuf *nam) |
| | | 102 | { |
| | | 103 | KASSERT(solocked(so)); |
| | | 104 | |
| | | 105 | return EOPNOTSUPP; |
| | | 106 | } |
| | | 107 | |
| | | 108 | static int |
| | | 109 | natm_bind(struct socket *so, struct mbuf *nam, struct lwp *l) |
| | | 110 | { |
| | | 111 | KASSERT(solocked(so)); |
| | | 112 | |
| | | 113 | return EOPNOTSUPP; |
| | | 114 | } |
| | | 115 | |
| | | 116 | static int |
| | | 117 | natm_listen(struct socket *so, struct lwp *l) |
| | | 118 | { |
| | | 119 | KASSERT(solocked(so)); |
| | | 120 | |
| | | 121 | return EOPNOTSUPP; |
| | | 122 | } |
| | | 123 | |
| | | 124 | static int |
| | | 125 | natm_connect(struct socket *so, struct mbuf *nam, struct lwp *l) |
| | | 126 | { |
| | | 127 | int error = 0, s2; |
| | | 128 | struct natmpcb *npcb; |
| | | 129 | struct sockaddr_natm *snatm; |
| | | 130 | struct atm_pseudoioctl api; |
| | | 131 | struct atm_pseudohdr *aph; |
| | | 132 | struct ifnet *ifp; |
| | | 133 | int proto = so->so_proto->pr_protocol; |
| | | 134 | |
| | | 135 | KASSERT(solocked(so)); |
| | | 136 | |
| | | 137 | /* |
| | | 138 | * validate nam and npcb |
| | | 139 | */ |
| | | 140 | |
| | | 141 | if (nam->m_len != sizeof(*snatm)) |
| | | 142 | return EINVAL; |
| | | 143 | snatm = mtod(nam, struct sockaddr_natm *); |
| | | 144 | if (snatm->snatm_len != sizeof(*snatm) || |
| | | 145 | (npcb->npcb_flags & NPCB_FREE) == 0) |
| | | 146 | return EINVAL; |
| | | 147 | if (snatm->snatm_family != AF_NATM) |
| | | 148 | return EAFNOSUPPORT; |
| | | 149 | |
| | | 150 | snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination |
| | | 151 | since ifunit() uses strcmp */ |
| | | 152 | |
| | | 153 | /* |
| | | 154 | * convert interface string to ifp, validate. |
| | | 155 | */ |
| | | 156 | |
| | | 157 | ifp = ifunit(snatm->snatm_if); |
| | | 158 | if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { |
| | | 159 | return ENXIO; |
| | | 160 | } |
| | | 161 | if (ifp->if_output != atm_output) { |
| | | 162 | return EAFNOSUPPORT; |
| | | 163 | } |
| | | 164 | |
| | | 165 | /* |
| | | 166 | * register us with the NATM PCB layer |
| | | 167 | */ |
| | | 168 | |
| | | 169 | if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) |
| | | 170 | return EADDRINUSE; |
| | | 171 | |
| | | 172 | /* |
| | | 173 | * enable rx |
| | | 174 | */ |
| | | 175 | |
| | | 176 | ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
| | | 177 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; |
| | | 178 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); |
| | | 179 | api.rxhand = npcb; |
| | | 180 | s2 = splnet(); |
| | | 181 | if (ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) { |
| | | 182 | splx(s2); |
| | | 183 | npcb_free(npcb, NPCB_REMOVE); |
| | | 184 | return EIO; |
| | | 185 | } |
| | | 186 | splx(s2); |
| | | 187 | |
| | | 188 | soisconnected(so); |
| | | 189 | return error; |
| | | 190 | } |
| | | 191 | |
| | | 192 | static int |
| | | 193 | natm_connect2(struct socket *so, struct socket *so2) |
| | | 194 | { |
| | | 195 | KASSERT(solocked(so)); |
| | | 196 | |
| | | 197 | return EOPNOTSUPP; |
| | | 198 | } |
| | | 199 | |
| | | 200 | static int |
| | | 201 | natm_disconnect(struct socket *so) |
| | | 202 | { |
| | | 203 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; |
| | | 204 | |
| | | 205 | KASSERT(solocked(so)); |
| | | 206 | KASSERT(npcb != NULL); |
| | | 207 | |
| | | 208 | if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { |
| | | 209 | printf("natm: disconnected check\n"); |
| | | 210 | return EIO; |
| | | 211 | } |
| | | 212 | ifp = npcb->npcb_ifp; |
| | | 213 | |
| | | 214 | /* |
| | | 215 | * disable rx |
| | | 216 | */ |
| | | 217 | ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; |
| | | 218 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; |
| | | 219 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); |
| | | 220 | api.rxhand = npcb; |
| | | 221 | |
| | | 222 | s2 = splnet(); |
| | | 223 | ifp->if_ioctl(ifp, SIOCATMDIS, &api); |
| | | 224 | splx(s); |
| | | 225 | |
| | | 226 | npcb_free(npcb, NPCB_REMOVE); |
| | | 227 | soisdisconnected(so); |
| | | 228 | return 0; |
| | | 229 | } |
| | | 230 | |
| | | 231 | static int |
| | | 232 | natm_shutdown(struct socket *so) |
| | | 233 | { |
| | | 234 | int s; |
| | | 235 | |
| | | 236 | KASSERT(solocked(so)); |
| | | 237 | |
| | | 238 | s = splsoftnet(); |
| | | 239 | socantsendmore(so); |
| | | 240 | splx(s); |
| | | 241 | |
| | | 242 | return 0; |
| | | 243 | } |
| | | 244 | |
| | | 245 | static int |
| | | 246 | natm_abort(struct socket *so) |
| | | 247 | { |
| | | 248 | KASSERT(solocked(so)); |
| | | 249 | |
| | | 250 | return EOPNOTSUPP; |
| | | 251 | } |
| | | 252 | |
| | | 253 | static int |
| | | 254 | natm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) |
| | | 255 | { |
| | | 256 | int error = 0, s; |
75 | struct natmpcb *npcb; | | 257 | struct natmpcb *npcb; |
76 | struct sockaddr_natm *snatm; | | | |
77 | struct atm_pseudoioctl api; | | | |
78 | struct atm_pseudohdr *aph; | | | |
79 | struct atm_rawioctl ario; | | 258 | struct atm_rawioctl ario; |
80 | struct ifnet *ifp; | | | |
81 | int proto = so->so_proto->pr_protocol; | | | |
82 | | | 259 | |
83 | s = SPLSOFTNET(); | | 260 | s = SPLSOFTNET(); |
84 | | | 261 | |
85 | npcb = (struct natmpcb *) so->so_pcb; | | 262 | npcb = (struct natmpcb *) so->so_pcb; |
86 | | | 263 | |
87 | if (npcb == NULL && req != PRU_ATTACH) { | | 264 | /* |
88 | error = EINVAL; | | 265 | * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to |
| | | 266 | * SIOCXRAWATM and pass it to the driver. |
| | | 267 | */ |
| | | 268 | if (cmd == SIOCRAWATM) { |
| | | 269 | if (npcb->npcb_ifp == NULL) { |
| | | 270 | error = ENOTCONN; |
| | | 271 | goto done; |
| | | 272 | } |
| | | 273 | ario.npcb = npcb; |
| | | 274 | ario.rawvalue = *((int *)nam); |
| | | 275 | error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario); |
| | | 276 | if (!error) { |
| | | 277 | if (ario.rawvalue) |
| | | 278 | npcb->npcb_flags |= NPCB_RAW; |
| | | 279 | else |
| | | 280 | npcb->npcb_flags &= ~(NPCB_RAW); |
| | | 281 | } |
| | | 282 | |
89 | goto done; | | 283 | goto done; |
90 | } | | 284 | } |
91 | | | 285 | |
| | | 286 | error = EOPNOTSUPP; |
92 | | | 287 | |
93 | switch (req) { | | 288 | done: |
94 | case PRU_ATTACH: /* attach protocol to up */ | | 289 | splx(s); |
| | | 290 | return(error); |
| | | 291 | } |
95 | | | 292 | |
96 | if (npcb) { | | 293 | static int |
97 | error = EISCONN; | | 294 | natm_stat(struct socket *so, struct stat *ub) |
98 | break; | | 295 | { |
99 | } | | 296 | KASSERT(solocked(so)); |
100 | | | | |
101 | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { | | | |
102 | if (proto == PROTO_NATMAAL5) | | | |
103 | error = soreserve(so, natm5_sendspace, natm5_recvspace); | | | |
104 | else | | | |
105 | error = soreserve(so, natm0_sendspace, natm0_recvspace); | | | |
106 | if (error) | | | |
107 | break; | | | |
108 | } | | | |
109 | | | 297 | |
110 | so->so_pcb = (void *) (npcb = npcb_alloc(M_WAITOK)); | | 298 | return 0; |
111 | npcb->npcb_socket = so; | | 299 | } |
112 | | | 300 | |
113 | break; | | 301 | static int |
| | | 302 | natm_peeraddr(struct socket *so, struct mbuf *nam) |
| | | 303 | { |
| | | 304 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
| | | 305 | struct sockaddr_natm *snatm; |
114 | | | 306 | |
115 | case PRU_DETACH: /* detach protocol from up */ | | 307 | KASSERT(solocked(so)); |
| | | 308 | KASSERT(pcb != NULL); |
| | | 309 | KASSERT(nam != NULL); |
| | | 310 | |
| | | 311 | snatm = mtod(nam, struct sockaddr_natm *); |
| | | 312 | memset(snatm, 0, sizeof(*snatm)); |
| | | 313 | nam->m_len = snatm->snatm_len = sizeof(*snatm); |
| | | 314 | snatm->snatm_family = AF_NATM; |
| | | 315 | memcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname, sizeof(snatm->snatm_if)); |
| | | 316 | snatm->snatm_vci = npcb->npcb_vci; |
| | | 317 | snatm->snatm_vpi = npcb->npcb_vpi; |
| | | 318 | return 0; |
| | | 319 | } |
116 | | | 320 | |
117 | /* | | 321 | static int |
118 | * we turn on 'drain' *before* we sofree. | | 322 | natm_sockaddr(struct socket *so, struct mbuf *nam) |
119 | */ | | 323 | { |
120 | | | 324 | KASSERT(solocked(so)); |
121 | npcb_free(npcb, NPCB_DESTROY); /* drain */ | | | |
122 | so->so_pcb = NULL; | | | |
123 | /* sofree drops the lock */ | | | |
124 | sofree(so); | | | |
125 | mutex_enter(softnet_lock); | | | |
126 | | | 325 | |
127 | break; | | 326 | return EOPNOTSUPP; |
| | | 327 | } |
128 | | | 328 | |
129 | case PRU_CONNECT: /* establish connection to peer */ | | 329 | static int |
| | | 330 | natm_rcvd(struct socket *so, int flags, struct lwp *l) |
| | | 331 | { |
| | | 332 | KASSERT(solocked(so)); |
130 | | | 333 | |
131 | /* | | 334 | return EOPNOTSUPP; |
132 | * validate nam and npcb | | 335 | } |
133 | */ | | | |
134 | | | | |
135 | if (nam->m_len != sizeof(*snatm)) { | | | |
136 | error = EINVAL; | | | |
137 | break; | | | |
138 | } | | | |
139 | snatm = mtod(nam, struct sockaddr_natm *); | | | |
140 | if (snatm->snatm_len != sizeof(*snatm) || | | | |
141 | (npcb->npcb_flags & NPCB_FREE) == 0) { | | | |
142 | error = EINVAL; | | | |
143 | break; | | | |
144 | } | | | |
145 | if (snatm->snatm_family != AF_NATM) { | | | |
146 | error = EAFNOSUPPORT; | | | |
147 | break; | | | |
148 | } | | | |
149 | | | 336 | |
150 | snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination | | 337 | static int |
151 | since ifunit() uses strcmp */ | | 338 | natm_recvoob(struct socket *so, struct mbuf *m, int flags) |
| | | 339 | { |
| | | 340 | KASSERT(solocked(so)); |
152 | | | 341 | |
153 | /* | | 342 | return EOPNOTSUPP; |
154 | * convert interface string to ifp, validate. | | 343 | } |
155 | */ | | | |
156 | | | | |
157 | ifp = ifunit(snatm->snatm_if); | | | |
158 | if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { | | | |
159 | error = ENXIO; | | | |
160 | break; | | | |
161 | } | | | |
162 | if (ifp->if_output != atm_output) { | | | |
163 | error = EAFNOSUPPORT; | | | |
164 | break; | | | |
165 | } | | | |
166 | | | | |
167 | | | | |
168 | /* | | | |
169 | * register us with the NATM PCB layer | | | |
170 | */ | | | |
171 | | | | |
172 | if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { | | | |
173 | error = EADDRINUSE; | | | |
174 | break; | | | |
175 | } | | | |
176 | | | | |
177 | /* | | | |
178 | * enable rx | | | |
179 | */ | | | |
180 | | | | |
181 | ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; | | | |
182 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; | | | |
183 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); | | | |
184 | api.rxhand = npcb; | | | |
185 | s2 = splnet(); | | | |
186 | if (ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) { | | | |
187 | splx(s2); | | | |
188 | npcb_free(npcb, NPCB_REMOVE); | | | |
189 | error = EIO; | | | |
190 | break; | | | |
191 | } | | | |
192 | splx(s2); | | | |
193 | | | 344 | |
194 | soisconnected(so); | | 345 | static int |
| | | 346 | natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam, |
| | | 347 | struct mbuf *control) |
| | | 348 | { |
| | | 349 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
| | | 350 | struct atm_pseudohdr *aph; |
195 | | | 351 | |
196 | break; | | 352 | KASSERT(solocked(so)); |
| | | 353 | KASSERT(pcb != NULL); |
| | | 354 | KASSERT(m != NULL); |
| | | 355 | |
| | | 356 | if (control && control->m_len) { |
| | | 357 | m_freem(control); |
| | | 358 | m_freem(m); |
| | | 359 | return EINVAL; |
| | | 360 | } |
197 | | | 361 | |
198 | case PRU_DISCONNECT: /* disconnect from peer */ | | 362 | /* |
| | | 363 | * send the data. we must put an atm_pseudohdr on first |
| | | 364 | */ |
| | | 365 | s = SPLSOFTNET(); |
| | | 366 | M_PREPEND(m, sizeof(*aph), M_WAITOK); |
| | | 367 | if (m == NULL) { |
| | | 368 | error = ENOBUFS; |
| | | 369 | break; |
| | | 370 | } |
| | | 371 | aph = mtod(m, struct atm_pseudohdr *); |
| | | 372 | ATM_PH_VPI(aph) = npcb->npcb_vpi; |
| | | 373 | ATM_PH_SETVCI(aph, npcb->npcb_vci); |
| | | 374 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
| | | 375 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); |
| | | 376 | splx(s); |
199 | | | 377 | |
200 | if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { | | 378 | return error; |
201 | printf("natm: disconnected check\n"); | | 379 | } |
202 | error = EIO; | | | |
203 | break; | | | |
204 | } | | | |
205 | ifp = npcb->npcb_ifp; | | | |
206 | | | | |
207 | /* | | | |
208 | * disable rx | | | |
209 | */ | | | |
210 | | | | |
211 | ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; | | | |
212 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; | | | |
213 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); | | | |
214 | api.rxhand = npcb; | | | |
215 | s2 = splnet(); | | | |
216 | ifp->if_ioctl(ifp, SIOCATMDIS, &api); | | | |
217 | splx(s); | | | |
218 | | | 380 | |
219 | npcb_free(npcb, NPCB_REMOVE); | | 381 | static int |
220 | soisdisconnected(so); | | 382 | natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam, |
| | | 383 | struct mbuf *control, struct lwp *l) |
| | | 384 | { |
| | | 385 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
| | | 386 | struct atm_pseudohdr *aph; |
221 | | | 387 | |
222 | break; | | 388 | KASSERT(solocked(so)); |
| | | 389 | KASSERT(pcb != NULL); |
| | | 390 | KASSERT(m != NULL); |
| | | 391 | |
| | | 392 | if (control && control->m_len) { |
| | | 393 | m_freem(control); |
| | | 394 | m_freem(m); |
| | | 395 | return EINVAL; |
| | | 396 | } |
223 | | | 397 | |
224 | case PRU_SHUTDOWN: /* won't send any more data */ | | 398 | /* |
225 | socantsendmore(so); | | 399 | * send the data. we must put an atm_pseudohdr on first |
226 | break; | | 400 | */ |
| | | 401 | s = SPLSOFTNET(); |
| | | 402 | M_PREPEND(m, sizeof(*aph), M_WAITOK); |
| | | 403 | if (m == NULL) { |
| | | 404 | error = ENOBUFS; |
| | | 405 | break; |
| | | 406 | } |
| | | 407 | aph = mtod(m, struct atm_pseudohdr *); |
| | | 408 | ATM_PH_VPI(aph) = npcb->npcb_vpi; |
| | | 409 | ATM_PH_SETVCI(aph, npcb->npcb_vci); |
| | | 410 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
| | | 411 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); |
| | | 412 | splx(s); |
227 | | | 413 | |
228 | case PRU_SEND: /* send this data */ | | 414 | return error; |
229 | if (control && control->m_len) { | | 415 | } |
230 | m_freem(control); | | | |
231 | m_freem(m); | | | |
232 | error = EINVAL; | | | |
233 | break; | | | |
234 | } | | | |
235 | | | | |
236 | /* | | | |
237 | * send the data. we must put an atm_pseudohdr on first | | | |
238 | */ | | | |
239 | | | | |
240 | M_PREPEND(m, sizeof(*aph), M_WAITOK); | | | |
241 | if (m == NULL) { | | | |
242 | error = ENOBUFS; | | | |
243 | break; | | | |
244 | } | | | |
245 | aph = mtod(m, struct atm_pseudohdr *); | | | |
246 | ATM_PH_VPI(aph) = npcb->npcb_vpi; | | | |
247 | ATM_PH_SETVCI(aph, npcb->npcb_vci); | | | |
248 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; | | | |
249 | | | 416 | |
250 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); | | 417 | static int |
| | | 418 | natm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) |
| | | 419 | { |
| | | 420 | KASSERT(solocked(so)); |
251 | | | 421 | |
252 | break; | | 422 | return EOPNOTSUPP; |
| | | 423 | } |
253 | | | 424 | |
254 | case PRU_SENSE: /* return status into m */ | | 425 | static int |
255 | /* return zero? */ | | 426 | natm_purgeif(struct socket *so, struct ifnet *ifp) |
256 | break; | | 427 | { |
257 | | | 428 | |
258 | case PRU_PEERADDR: /* fetch peer's address */ | | 429 | return EOPNOTSUPP; |
259 | snatm = mtod(nam, struct sockaddr_natm *); | | 430 | } |
260 | memset(snatm, 0, sizeof(*snatm)); | | | |
261 | nam->m_len = snatm->snatm_len = sizeof(*snatm); | | | |
262 | snatm->snatm_family = AF_NATM; | | | |
263 | memcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname, sizeof(snatm->snatm_if)); | | | |
264 | snatm->snatm_vci = npcb->npcb_vci; | | | |
265 | snatm->snatm_vpi = npcb->npcb_vpi; | | | |
266 | break; | | | |
267 | | | 431 | |
268 | case PRU_CONTROL: /* control operations on protocol */ | | 432 | /* |
269 | /* | | 433 | * user requests |
270 | * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to | | 434 | */ |
271 | * SIOCXRAWATM and pass it to the driver. | | | |
272 | */ | | | |
273 | if ((u_long)m == SIOCRAWATM) { | | | |
274 | if (npcb->npcb_ifp == NULL) { | | | |
275 | error = ENOTCONN; | | | |
276 | break; | | | |
277 | } | | | |
278 | ario.npcb = npcb; | | | |
279 | ario.rawvalue = *((int *)nam); | | | |
280 | error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario); | | | |
281 | if (!error) { | | | |
282 | if (ario.rawvalue) | | | |
283 | npcb->npcb_flags |= NPCB_RAW; | | | |
284 | else | | | |
285 | npcb->npcb_flags &= ~(NPCB_RAW); | | | |
286 | } | | | |
287 | | | 435 | |
288 | break; | | 436 | static int |
289 | } | | 437 | natm_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, |
| | | 438 | struct mbuf *control, struct lwp *l) |
| | | 439 | { |
| | | 440 | int error = 0, s, s2; |
| | | 441 | struct natmpcb *npcb; |
| | | 442 | struct sockaddr_natm *snatm; |
| | | 443 | struct atm_pseudoioctl api; |
| | | 444 | struct atm_pseudohdr *aph; |
| | | 445 | struct ifnet *ifp; |
| | | 446 | int proto = so->so_proto->pr_protocol; |
290 | | | 447 | |
291 | error = EOPNOTSUPP; | | 448 | KASSERT(req != PRU_ATTACH); |
292 | break; | | 449 | KASSERT(req != PRU_DETACH); |
| | | 450 | KASSERT(req != PRU_ACCEPT); |
| | | 451 | KASSERT(req != PRU_BIND); |
| | | 452 | KASSERT(req != PRU_LISTEN); |
| | | 453 | KASSERT(req != PRU_CONNECT); |
| | | 454 | KASSERT(req != PRU_CONNECT2); |
| | | 455 | KASSERT(req != PRU_DISCONNECT); |
| | | 456 | KASSERT(req != PRU_SHUTDOWN); |
| | | 457 | KASSERT(req != PRU_ABORT); |
| | | 458 | KASSERT(req != PRU_CONTROL); |
| | | 459 | KASSERT(req != PRU_SENSE); |
| | | 460 | KASSERT(req != PRU_PEERADDR); |
| | | 461 | KASSERT(req != PRU_SOCKADDR); |
| | | 462 | KASSERT(req != PRU_RCVD); |
| | | 463 | KASSERT(req != PRU_RCVOOB); |
| | | 464 | KASSERT(req != PRU_SEND); |
| | | 465 | KASSERT(req != PRU_SENDOOB); |
| | | 466 | KASSERT(req != PRU_PURGEIF); |
293 | | | 467 | |
294 | case PRU_BIND: /* bind socket to address */ | | 468 | if (so->so_pcb == NULL) |
295 | case PRU_LISTEN: /* listen for connection */ | | 469 | return EINVAL; |
296 | case PRU_ACCEPT: /* accept connection from peer */ | | 470 | |
297 | case PRU_CONNECT2: /* connect two sockets */ | | 471 | switch (req) { |
298 | case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */ | | | |
299 | /* (only happens if LISTEN socket) */ | | | |
300 | case PRU_RCVD: /* have taken data; more room now */ | | | |
301 | case PRU_FASTTIMO: /* 200ms timeout */ | | 472 | case PRU_FASTTIMO: /* 200ms timeout */ |
302 | case PRU_SLOWTIMO: /* 500ms timeout */ | | 473 | case PRU_SLOWTIMO: /* 500ms timeout */ |
303 | case PRU_RCVOOB: /* retrieve out of band data */ | | | |
304 | case PRU_SENDOOB: /* send out of band data */ | | | |
305 | case PRU_PROTORCV: /* receive from below */ | | 474 | case PRU_PROTORCV: /* receive from below */ |
306 | case PRU_PROTOSEND: /* send to below */ | | 475 | case PRU_PROTOSEND: /* send to below */ |
307 | case PRU_SOCKADDR: /* fetch socket's address */ | | | |
308 | #ifdef DIAGNOSTIC | | 476 | #ifdef DIAGNOSTIC |
309 | printf("natm: PRU #%d unsupported\n", req); | | 477 | printf("natm: PRU #%d unsupported\n", req); |
310 | #endif | | 478 | #endif |
311 | error = EOPNOTSUPP; | | 479 | error = EOPNOTSUPP; |
312 | break; | | 480 | break; |
313 | | | 481 | |
314 | default: panic("natm usrreq"); | | 482 | default: panic("natm usrreq"); |
315 | } | | 483 | } |
316 | | | 484 | |
317 | done: | | 485 | done: |
318 | splx(s); | | 486 | return error; |
319 | return(error); | | | |
320 | } | | 487 | } |
321 | | | 488 | |
322 | /* | | 489 | /* |
323 | * natmintr: splsoftnet interrupt | | 490 | * natmintr: splsoftnet interrupt |
324 | * | | 491 | * |
325 | * note: we expect a socket pointer in rcvif rather than an interface | | 492 | * note: we expect a socket pointer in rcvif rather than an interface |
326 | * pointer. we can get the interface pointer from the so's PCB if | | 493 | * pointer. we can get the interface pointer from the so's PCB if |
327 | * we really need it. | | 494 | * we really need it. |
328 | */ | | 495 | */ |
329 | | | 496 | |
330 | void | | 497 | void |
331 | natmintr(void) | | 498 | natmintr(void) |
332 | | | 499 | |
| @@ -351,27 +518,27 @@ next: | | | @@ -351,27 +518,27 @@ next: |
351 | panic("natmintr no HDR"); | | 518 | panic("natmintr no HDR"); |
352 | #endif | | 519 | #endif |
353 | | | 520 | |
354 | npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ | | 521 | npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ |
355 | so = npcb->npcb_socket; | | 522 | so = npcb->npcb_socket; |
356 | | | 523 | |
357 | s = splnet(); /* could have atm devs @ different levels */ | | 524 | s = splnet(); /* could have atm devs @ different levels */ |
358 | npcb->npcb_inq--; | | 525 | npcb->npcb_inq--; |
359 | splx(s); | | 526 | splx(s); |
360 | | | 527 | |
361 | if (npcb->npcb_flags & NPCB_DRAIN) { | | 528 | if (npcb->npcb_flags & NPCB_DRAIN) { |
362 | m_freem(m); | | 529 | m_freem(m); |
363 | if (npcb->npcb_inq == 0) | | 530 | if (npcb->npcb_inq == 0) |
364 | free(npcb, M_PCB); /* done! */ | | 531 | kmem_intr_free(npcb, sizeof(*npcb)); |
365 | goto next; | | 532 | goto next; |
366 | } | | 533 | } |
367 | | | 534 | |
368 | if (npcb->npcb_flags & NPCB_FREE) { | | 535 | if (npcb->npcb_flags & NPCB_FREE) { |
369 | m_freem(m); /* drop */ | | 536 | m_freem(m); /* drop */ |
370 | goto next; | | 537 | goto next; |
371 | } | | 538 | } |
372 | | | 539 | |
373 | #ifdef NEED_TO_RESTORE_IFP | | 540 | #ifdef NEED_TO_RESTORE_IFP |
374 | m->m_pkthdr.rcvif = npcb->npcb_ifp; | | 541 | m->m_pkthdr.rcvif = npcb->npcb_ifp; |
375 | #else | | 542 | #else |
376 | #ifdef DIAGNOSTIC | | 543 | #ifdef DIAGNOSTIC |
377 | m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ | | 544 | m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ |
| @@ -386,13 +553,58 @@ m->m_pkthdr.rcvif = NULL; /* null it out | | | @@ -386,13 +553,58 @@ m->m_pkthdr.rcvif = NULL; /* null it out |
386 | #endif | | 553 | #endif |
387 | sbappendrecord(&so->so_rcv, m); | | 554 | sbappendrecord(&so->so_rcv, m); |
388 | sorwakeup(so); | | 555 | sorwakeup(so); |
389 | } else { | | 556 | } else { |
390 | #ifdef NATM_STAT | | 557 | #ifdef NATM_STAT |
391 | natm_sodropcnt++; | | 558 | natm_sodropcnt++; |
392 | natm_sodropbytes += m->m_pkthdr.len; | | 559 | natm_sodropbytes += m->m_pkthdr.len; |
393 | #endif | | 560 | #endif |
394 | m_freem(m); | | 561 | m_freem(m); |
395 | } | | 562 | } |
396 | | | 563 | |
397 | goto next; | | 564 | goto next; |
398 | } | | 565 | } |
| | | 566 | |
| | | 567 | PR_WRAP_USRREQS(natm) |
| | | 568 | #define natm_attach natm_attach_wrapper |
| | | 569 | #define natm_detach natm_detach_wrapper |
| | | 570 | #define natm_accept natm_accept_wrapper |
| | | 571 | #define natm_bind natm_bind_wrapper |
| | | 572 | #define natm_listen natm_listen_wrapper |
| | | 573 | #define natm_connect natm_connect_wrapper |
| | | 574 | #define natm_connect2 natm_connect2_wrapper |
| | | 575 | #define natm_disconnect natm_disconnect_wrapper |
| | | 576 | #define natm_shutdown natm_shutdown_wrapper |
| | | 577 | #define natm_abort natm_abort_wrapper |
| | | 578 | #define natm_ioctl natm_ioctl_wrapper |
| | | 579 | #define natm_stat natm_stat_wrapper |
| | | 580 | #define natm_peeraddr natm_peeraddr_wrapper |
| | | 581 | #define natm_sockaddr natm_sockaddr_wrapper |
| | | 582 | #define natm_rcvd natm_rcvd_wrapper |
| | | 583 | #define natm_recvoob natm_recvoob_wrapper |
| | | 584 | #define natm_send natm_send_wrapper |
| | | 585 | #define natm_sendoob natm_sendoob_wrapper |
| | | 586 | #define natm_purgeif natm_purgeif_wrapper |
| | | 587 | #define natm_usrreq natm_usrreq_wrapper |
| | | 588 | |
| | | 589 | const struct pr_usrreqs natm_usrreqs = { |
| | | 590 | .pr_attach = natm_attach, |
| | | 591 | .pr_detach = natm_detach, |
| | | 592 | .pr_accept = natm_accept, |
| | | 593 | .pr_bind = natm_bind, |
| | | 594 | .pr_listen = natm_listen, |
| | | 595 | .pr_connect = natm_connect, |
| | | 596 | .pr_connect2 = natm_connect2, |
| | | 597 | .pr_disconnect = natm_disconnect, |
| | | 598 | .pr_shutdown = natm_shutdown, |
| | | 599 | .pr_abort = natm_abort, |
| | | 600 | .pr_ioctl = natm_ioctl, |
| | | 601 | .pr_stat = natm_stat, |
| | | 602 | .pr_peeraddr = natm_peeraddr, |
| | | 603 | .pr_sockaddr = natm_sockaddr, |
| | | 604 | .pr_rcvd = natm_rcvd, |
| | | 605 | .pr_recvoob = natm_recvoob, |
| | | 606 | .pr_send = natm_send, |
| | | 607 | .pr_sendoob = natm_sendoob, |
| | | 608 | .pr_purgeif = natm_purgeif, |
| | | 609 | .pr_generic = natm_usrreq, |
| | | 610 | }; |