1/* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $ */ 2 3/* 4 * 5 * Copyright (c) 1996 Charles D. Cranor and Washington University. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Charles D. Cranor and 19 * Washington University. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * natm.c: native mode ATM access (both aal0 and aal5). 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/domain.h> 43#if defined(__FreeBSD__) 44#include <sys/sockio.h> 45#else 46#include <sys/ioctl.h> 47#endif 48#include <sys/proc.h> 49#include <sys/protosw.h> 50#include <sys/mbuf.h> 51#include <sys/socket.h> 52#include <sys/socketvar.h> 53 54#include <net/if.h> 55#include <net/if_atm.h> 56#include <net/netisr.h> 57#include <net/radix.h> 58#include <net/route.h> 59 60#include <netinet/in.h> 61 62#include <netnatm/natm.h> 63 64u_long natm5_sendspace = 16*1024; 65u_long natm5_recvspace = 16*1024; 66 67u_long natm0_sendspace = 16*1024; 68u_long natm0_recvspace = 16*1024; 69 70/* 71 * user requests 72 */ 73#ifdef FREEBSD_USRREQS 74/* 75 * FreeBSD new usrreqs supersedes pr_usrreq. 76 */ 77static int natm_usr_attach __P((struct socket *, int, struct proc *)); 78static int natm_usr_detach __P((struct socket *));
| 1/* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $ */ 2 3/* 4 * 5 * Copyright (c) 1996 Charles D. Cranor and Washington University. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Charles D. Cranor and 19 * Washington University. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35/* 36 * natm.c: native mode ATM access (both aal0 and aal5). 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> 42#include <sys/domain.h> 43#if defined(__FreeBSD__) 44#include <sys/sockio.h> 45#else 46#include <sys/ioctl.h> 47#endif 48#include <sys/proc.h> 49#include <sys/protosw.h> 50#include <sys/mbuf.h> 51#include <sys/socket.h> 52#include <sys/socketvar.h> 53 54#include <net/if.h> 55#include <net/if_atm.h> 56#include <net/netisr.h> 57#include <net/radix.h> 58#include <net/route.h> 59 60#include <netinet/in.h> 61 62#include <netnatm/natm.h> 63 64u_long natm5_sendspace = 16*1024; 65u_long natm5_recvspace = 16*1024; 66 67u_long natm0_sendspace = 16*1024; 68u_long natm0_recvspace = 16*1024; 69 70/* 71 * user requests 72 */ 73#ifdef FREEBSD_USRREQS 74/* 75 * FreeBSD new usrreqs supersedes pr_usrreq. 76 */ 77static int natm_usr_attach __P((struct socket *, int, struct proc *)); 78static int natm_usr_detach __P((struct socket *));
|
79static int natm_usr_connect __P((struct socket *, struct mbuf *,
| 79static int natm_usr_connect __P((struct socket *, struct sockaddr *,
|
80 struct proc *)); 81static int natm_usr_disconnect __P((struct socket *)); 82static int natm_usr_shutdown __P((struct socket *)); 83static int natm_usr_send __P((struct socket *, int, struct mbuf *,
| 80 struct proc *)); 81static int natm_usr_disconnect __P((struct socket *)); 82static int natm_usr_shutdown __P((struct socket *)); 83static int natm_usr_send __P((struct socket *, int, struct mbuf *,
|
84 struct mbuf *, struct mbuf *, struct proc *)); 85static int natm_usr_peeraddr __P((struct socket *, struct mbuf *));
| 84 struct sockaddr *, struct mbuf *, 85 struct proc *)); 86static int natm_usr_peeraddr __P((struct socket *, struct sockaddr **));
|
86static int natm_usr_control __P((struct socket *, int, caddr_t, 87 struct ifnet *, struct proc *)); 88static int natm_usr_abort __P((struct socket *));
| 87static int natm_usr_control __P((struct socket *, int, caddr_t, 88 struct ifnet *, struct proc *)); 89static int natm_usr_abort __P((struct socket *));
|
89static int natm_usr_bind __P((struct socket *, struct mbuf *, struct proc *)); 90static int natm_usr_sockaddr __P((struct socket *, struct mbuf *));
| 90static int natm_usr_bind __P((struct socket *, struct sockaddr *, 91 struct proc *)); 92static int natm_usr_sockaddr __P((struct socket *, struct sockaddr **));
|
91 92static int 93natm_usr_attach(struct socket *so, int proto, struct proc *p) 94{ 95 struct natmpcb *npcb; 96 int error = 0; 97 int s = SPLSOFTNET(); 98 99 npcb = (struct natmpcb *) so->so_pcb; 100 101 if (npcb) { 102 error = EISCONN; 103 goto out; 104 } 105 106 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 107 if (proto == PROTO_NATMAAL5) 108 error = soreserve(so, natm5_sendspace, natm5_recvspace); 109 else 110 error = soreserve(so, natm0_sendspace, natm0_recvspace); 111 if (error) 112 goto out; 113 } 114 115 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 116 npcb->npcb_socket = so; 117 out: 118 splx(s); 119 return (error); 120} 121 122static int 123natm_usr_detach(struct socket *so) 124{ 125 struct natmpcb *npcb; 126 int error = 0; 127 int s = SPLSOFTNET(); 128 129 npcb = (struct natmpcb *) so->so_pcb; 130 if (npcb == NULL) { 131 error = EINVAL; 132 goto out; 133 } 134 135 /* 136 * we turn on 'drain' *before* we sofree. 137 */ 138 npcb_free(npcb, NPCB_DESTROY); /* drain */ 139 so->so_pcb = NULL; 140 sofree(so); 141 out: 142 splx(s); 143 return (error); 144} 145 146static int
| 93 94static int 95natm_usr_attach(struct socket *so, int proto, struct proc *p) 96{ 97 struct natmpcb *npcb; 98 int error = 0; 99 int s = SPLSOFTNET(); 100 101 npcb = (struct natmpcb *) so->so_pcb; 102 103 if (npcb) { 104 error = EISCONN; 105 goto out; 106 } 107 108 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 109 if (proto == PROTO_NATMAAL5) 110 error = soreserve(so, natm5_sendspace, natm5_recvspace); 111 else 112 error = soreserve(so, natm0_sendspace, natm0_recvspace); 113 if (error) 114 goto out; 115 } 116 117 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 118 npcb->npcb_socket = so; 119 out: 120 splx(s); 121 return (error); 122} 123 124static int 125natm_usr_detach(struct socket *so) 126{ 127 struct natmpcb *npcb; 128 int error = 0; 129 int s = SPLSOFTNET(); 130 131 npcb = (struct natmpcb *) so->so_pcb; 132 if (npcb == NULL) { 133 error = EINVAL; 134 goto out; 135 } 136 137 /* 138 * we turn on 'drain' *before* we sofree. 139 */ 140 npcb_free(npcb, NPCB_DESTROY); /* drain */ 141 so->so_pcb = NULL; 142 sofree(so); 143 out: 144 splx(s); 145 return (error); 146} 147 148static int
|
147natm_usr_connect(struct socket *so, struct mbuf *nam, struct proc *p)
| 149natm_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
|
148{ 149 struct natmpcb *npcb; 150 struct sockaddr_natm *snatm; 151 struct atm_pseudoioctl api; 152 struct atm_pseudohdr *aph; 153 struct ifnet *ifp; 154 int error = 0; 155 int s2, s = SPLSOFTNET(); 156 int proto = so->so_proto->pr_protocol; 157 158 npcb = (struct natmpcb *) so->so_pcb; 159 if (npcb == NULL) { 160 error = EINVAL; 161 goto out; 162 } 163 164 /* 165 * validate nam and npcb 166 */ 167
| 150{ 151 struct natmpcb *npcb; 152 struct sockaddr_natm *snatm; 153 struct atm_pseudoioctl api; 154 struct atm_pseudohdr *aph; 155 struct ifnet *ifp; 156 int error = 0; 157 int s2, s = SPLSOFTNET(); 158 int proto = so->so_proto->pr_protocol; 159 160 npcb = (struct natmpcb *) so->so_pcb; 161 if (npcb == NULL) { 162 error = EINVAL; 163 goto out; 164 } 165 166 /* 167 * validate nam and npcb 168 */ 169
|
168 if (nam->m_len != sizeof(*snatm)) { 169 error = EINVAL; 170 goto out; 171 } 172 snatm = mtod(nam, struct sockaddr_natm *);
| 170 snatm = (struct sockaddr_natm *)nam;
|
173 if (snatm->snatm_len != sizeof(*snatm) || 174 (npcb->npcb_flags & NPCB_FREE) == 0) { 175 error = EINVAL; 176 goto out; 177 } 178 if (snatm->snatm_family != AF_NATM) { 179 error = EAFNOSUPPORT; 180 goto out; 181 } 182 183 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination 184 since ifunit() uses strcmp */ 185 186 /* 187 * convert interface string to ifp, validate. 188 */ 189 190 ifp = ifunit(snatm->snatm_if); 191 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { 192 error = ENXIO; 193 goto out; 194 } 195 if (ifp->if_output != atm_output) { 196 error = EAFNOSUPPORT; 197 goto out; 198 } 199 200 /* 201 * register us with the NATM PCB layer 202 */ 203 204 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { 205 error = EADDRINUSE; 206 goto out; 207 } 208 209 /* 210 * enable rx 211 */ 212 213 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 214 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 215 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 216 api.rxhand = npcb; 217 s2 = splimp(); 218 if (ifp->if_ioctl == NULL || 219 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) { 220 splx(s2); 221 npcb_free(npcb, NPCB_REMOVE); 222 error = EIO; 223 goto out; 224 } 225 splx(s2); 226 227 soisconnected(so); 228 229 out: 230 splx(s); 231 return (error); 232} 233 234static int 235natm_usr_disconnect(struct socket *so) 236{ 237 struct natmpcb *npcb; 238 struct sockaddr_natm *snatm; 239 struct atm_pseudoioctl api; 240 struct atm_pseudohdr *aph; 241 struct ifnet *ifp; 242 int error = 0; 243 int s2, s = SPLSOFTNET(); 244 int proto = so->so_proto->pr_protocol; 245 246 npcb = (struct natmpcb *) so->so_pcb; 247 if (npcb == NULL) { 248 error = EINVAL; 249 goto out; 250 } 251 252 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 253 printf("natm: disconnected check\n"); 254 error = EIO; 255 goto out; 256 } 257 ifp = npcb->npcb_ifp; 258 259 /* 260 * disable rx 261 */ 262 263 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 264 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 265 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 266 api.rxhand = npcb; 267 s2 = splimp(); 268 if (ifp->if_ioctl != NULL) 269 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 270 splx(s2); 271 272 npcb_free(npcb, NPCB_REMOVE); 273 soisdisconnected(so); 274 275 out: 276 splx(s); 277 return (error); 278} 279 280static int 281natm_usr_shutdown(struct socket *so) 282{ 283 socantsendmore(so); 284 return 0; 285} 286 287static int
| 171 if (snatm->snatm_len != sizeof(*snatm) || 172 (npcb->npcb_flags & NPCB_FREE) == 0) { 173 error = EINVAL; 174 goto out; 175 } 176 if (snatm->snatm_family != AF_NATM) { 177 error = EAFNOSUPPORT; 178 goto out; 179 } 180 181 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination 182 since ifunit() uses strcmp */ 183 184 /* 185 * convert interface string to ifp, validate. 186 */ 187 188 ifp = ifunit(snatm->snatm_if); 189 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { 190 error = ENXIO; 191 goto out; 192 } 193 if (ifp->if_output != atm_output) { 194 error = EAFNOSUPPORT; 195 goto out; 196 } 197 198 /* 199 * register us with the NATM PCB layer 200 */ 201 202 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { 203 error = EADDRINUSE; 204 goto out; 205 } 206 207 /* 208 * enable rx 209 */ 210 211 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 212 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 213 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 214 api.rxhand = npcb; 215 s2 = splimp(); 216 if (ifp->if_ioctl == NULL || 217 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) { 218 splx(s2); 219 npcb_free(npcb, NPCB_REMOVE); 220 error = EIO; 221 goto out; 222 } 223 splx(s2); 224 225 soisconnected(so); 226 227 out: 228 splx(s); 229 return (error); 230} 231 232static int 233natm_usr_disconnect(struct socket *so) 234{ 235 struct natmpcb *npcb; 236 struct sockaddr_natm *snatm; 237 struct atm_pseudoioctl api; 238 struct atm_pseudohdr *aph; 239 struct ifnet *ifp; 240 int error = 0; 241 int s2, s = SPLSOFTNET(); 242 int proto = so->so_proto->pr_protocol; 243 244 npcb = (struct natmpcb *) so->so_pcb; 245 if (npcb == NULL) { 246 error = EINVAL; 247 goto out; 248 } 249 250 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 251 printf("natm: disconnected check\n"); 252 error = EIO; 253 goto out; 254 } 255 ifp = npcb->npcb_ifp; 256 257 /* 258 * disable rx 259 */ 260 261 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 262 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 263 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 264 api.rxhand = npcb; 265 s2 = splimp(); 266 if (ifp->if_ioctl != NULL) 267 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 268 splx(s2); 269 270 npcb_free(npcb, NPCB_REMOVE); 271 soisdisconnected(so); 272 273 out: 274 splx(s); 275 return (error); 276} 277 278static int 279natm_usr_shutdown(struct socket *so) 280{ 281 socantsendmore(so); 282 return 0; 283} 284 285static int
|
288natm_usr_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, 289 struct mbuf *control, struct proc *p)
| 286natm_usr_send(struct socket *so, int flags, struct mbuf *m, 287 struct sockaddr *nam, struct mbuf *control, struct proc *p)
|
290{ 291 struct natmpcb *npcb; 292 struct atm_pseudohdr *aph; 293 int error = 0; 294 int s = SPLSOFTNET(); 295 int proto = so->so_proto->pr_protocol; 296 297 npcb = (struct natmpcb *) so->so_pcb; 298 if (npcb == NULL) { 299 error = EINVAL; 300 goto out; 301 } 302 303 if (control && control->m_len) { 304 m_freem(control); 305 m_freem(m); 306 error = EINVAL; 307 goto out; 308 } 309 310 /* 311 * send the data. we must put an atm_pseudohdr on first 312 */ 313 314 M_PREPEND(m, sizeof(*aph), M_WAITOK); 315 if (m == NULL) { 316 error = ENOBUFS; 317 goto out; 318 } 319 aph = mtod(m, struct atm_pseudohdr *); 320 ATM_PH_VPI(aph) = npcb->npcb_vpi; 321 ATM_PH_SETVCI(aph, npcb->npcb_vci); 322 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 323 324 error = atm_output(npcb->npcb_ifp, m, NULL, NULL); 325 326 out: 327 splx(s); 328 return (error); 329} 330 331static int
| 288{ 289 struct natmpcb *npcb; 290 struct atm_pseudohdr *aph; 291 int error = 0; 292 int s = SPLSOFTNET(); 293 int proto = so->so_proto->pr_protocol; 294 295 npcb = (struct natmpcb *) so->so_pcb; 296 if (npcb == NULL) { 297 error = EINVAL; 298 goto out; 299 } 300 301 if (control && control->m_len) { 302 m_freem(control); 303 m_freem(m); 304 error = EINVAL; 305 goto out; 306 } 307 308 /* 309 * send the data. we must put an atm_pseudohdr on first 310 */ 311 312 M_PREPEND(m, sizeof(*aph), M_WAITOK); 313 if (m == NULL) { 314 error = ENOBUFS; 315 goto out; 316 } 317 aph = mtod(m, struct atm_pseudohdr *); 318 ATM_PH_VPI(aph) = npcb->npcb_vpi; 319 ATM_PH_SETVCI(aph, npcb->npcb_vci); 320 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 321 322 error = atm_output(npcb->npcb_ifp, m, NULL, NULL); 323 324 out: 325 splx(s); 326 return (error); 327} 328 329static int
|
332natm_usr_peeraddr(struct socket *so, struct mbuf *nam)
| 330natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
|
333{ 334 struct natmpcb *npcb;
| 331{ 332 struct natmpcb *npcb;
|
335 struct sockaddr_natm *snatm;
| 333 struct sockaddr_natm *snatm, ssnatm;
|
336 int error = 0; 337 int s = SPLSOFTNET(); 338 339 npcb = (struct natmpcb *) so->so_pcb; 340 if (npcb == NULL) { 341 error = EINVAL; 342 goto out; 343 } 344
| 334 int error = 0; 335 int s = SPLSOFTNET(); 336 337 npcb = (struct natmpcb *) so->so_pcb; 338 if (npcb == NULL) { 339 error = EINVAL; 340 goto out; 341 } 342
|
345 snatm = mtod(nam, struct sockaddr_natm *);
| 343 snatm = &ssnatm;
|
346 bzero(snatm, sizeof(*snatm));
| 344 bzero(snatm, sizeof(*snatm));
|
347 nam->m_len = snatm->snatm_len = sizeof(*snatm);
| 345 snatm->snatm_len = sizeof(*snatm);
|
348 snatm->snatm_family = AF_NATM; 349 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name, 350 npcb->npcb_ifp->if_unit); 351 snatm->snatm_vci = npcb->npcb_vci; 352 snatm->snatm_vpi = npcb->npcb_vpi;
| 346 snatm->snatm_family = AF_NATM; 347 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name, 348 npcb->npcb_ifp->if_unit); 349 snatm->snatm_vci = npcb->npcb_vci; 350 snatm->snatm_vpi = npcb->npcb_vpi;
|
| 351 *nam = dup_sockaddr((struct sockaddr *)snatm, 0);
|
353 354 out: 355 splx(s); 356 return (error); 357} 358 359static int 360natm_usr_control(struct socket *so, int cmd, caddr_t arg, 361 struct ifnet *ifp, struct proc *p) 362{ 363 struct natmpcb *npcb; 364 struct atm_rawioctl ario; 365 int error = 0; 366 int s = SPLSOFTNET(); 367 368 npcb = (struct natmpcb *) so->so_pcb; 369 if (npcb == NULL) { 370 error = EINVAL; 371 goto out; 372 } 373 374 /* 375 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 376 * SIOCXRAWATM and pass it to the driver. 377 */ 378 if (cmd == SIOCRAWATM) { 379 if (npcb->npcb_ifp == NULL) { 380 error = ENOTCONN; 381 goto out; 382 } 383 ario.npcb = npcb; 384 ario.rawvalue = *((int *)arg); 385 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 386 SIOCXRAWATM, (caddr_t) &ario); 387 if (!error) { 388 if (ario.rawvalue) 389 npcb->npcb_flags |= NPCB_RAW; 390 else 391 npcb->npcb_flags &= ~(NPCB_RAW); 392 } 393 } 394 else 395 error = EOPNOTSUPP; 396 397 out: 398 splx(s); 399 return (error); 400} 401 402static int 403natm_usr_abort(struct socket *so) 404{ 405 return natm_usr_shutdown(so); 406} 407 408static int
| 352 353 out: 354 splx(s); 355 return (error); 356} 357 358static int 359natm_usr_control(struct socket *so, int cmd, caddr_t arg, 360 struct ifnet *ifp, struct proc *p) 361{ 362 struct natmpcb *npcb; 363 struct atm_rawioctl ario; 364 int error = 0; 365 int s = SPLSOFTNET(); 366 367 npcb = (struct natmpcb *) so->so_pcb; 368 if (npcb == NULL) { 369 error = EINVAL; 370 goto out; 371 } 372 373 /* 374 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 375 * SIOCXRAWATM and pass it to the driver. 376 */ 377 if (cmd == SIOCRAWATM) { 378 if (npcb->npcb_ifp == NULL) { 379 error = ENOTCONN; 380 goto out; 381 } 382 ario.npcb = npcb; 383 ario.rawvalue = *((int *)arg); 384 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 385 SIOCXRAWATM, (caddr_t) &ario); 386 if (!error) { 387 if (ario.rawvalue) 388 npcb->npcb_flags |= NPCB_RAW; 389 else 390 npcb->npcb_flags &= ~(NPCB_RAW); 391 } 392 } 393 else 394 error = EOPNOTSUPP; 395 396 out: 397 splx(s); 398 return (error); 399} 400 401static int 402natm_usr_abort(struct socket *so) 403{ 404 return natm_usr_shutdown(so); 405} 406 407static int
|
409natm_usr_bind(struct socket *so, struct mbuf *nam, struct proc *p)
| 408natm_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
|
410{ 411 return EOPNOTSUPP; 412} 413 414static int
| 409{ 410 return EOPNOTSUPP; 411} 412 413static int
|
415natm_usr_sockaddr(struct socket *so, struct mbuf *nam)
| 414natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
|
416{ 417 return EOPNOTSUPP; 418} 419 420/* xxx - should be const */ 421struct pr_usrreqs natm_usrreqs = { 422 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind, 423 natm_usr_connect, pru_connect2_notsupp, natm_usr_control, 424 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp, 425 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, 426 natm_usr_send, pru_sense_null, natm_usr_shutdown, 427 natm_usr_sockaddr, sosend, soreceive, soselect 428}; 429 430#else /* !FREEBSD_USRREQS */ 431 432#if defined(__NetBSD__) || defined(__OpenBSD__) 433int natm_usrreq(so, req, m, nam, control, p) 434#elif defined(__FreeBSD__) 435int natm_usrreq(so, req, m, nam, control) 436#endif 437 438struct socket *so; 439int req; 440struct mbuf *m, *nam, *control; 441#if defined(__NetBSD__) || defined(__OpenBSD__) 442struct proc *p; 443#endif 444 445{ 446 int error = 0, s, s2; 447 struct natmpcb *npcb; 448 struct sockaddr_natm *snatm; 449 struct atm_pseudoioctl api; 450 struct atm_pseudohdr *aph; 451 struct atm_rawioctl ario; 452 struct ifnet *ifp; 453 int proto = so->so_proto->pr_protocol; 454 455 s = SPLSOFTNET(); 456 457 npcb = (struct natmpcb *) so->so_pcb; 458 459 if (npcb == NULL && req != PRU_ATTACH) { 460 error = EINVAL; 461 goto done; 462 } 463 464 465 switch (req) { 466 case PRU_ATTACH: /* attach protocol to up */ 467 468 if (npcb) { 469 error = EISCONN; 470 break; 471 } 472 473 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 474 if (proto == PROTO_NATMAAL5) 475 error = soreserve(so, natm5_sendspace, natm5_recvspace); 476 else 477 error = soreserve(so, natm0_sendspace, natm0_recvspace); 478 if (error) 479 break; 480 } 481 482 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 483 npcb->npcb_socket = so; 484 485 break; 486 487 case PRU_DETACH: /* detach protocol from up */ 488 489 /* 490 * we turn on 'drain' *before* we sofree. 491 */ 492 493 npcb_free(npcb, NPCB_DESTROY); /* drain */ 494 so->so_pcb = NULL; 495 sofree(so); 496 497 break; 498 499 case PRU_CONNECT: /* establish connection to peer */ 500 501 /* 502 * validate nam and npcb 503 */ 504 505 if (nam->m_len != sizeof(*snatm)) { 506 error = EINVAL; 507 break; 508 } 509 snatm = mtod(nam, struct sockaddr_natm *); 510 if (snatm->snatm_len != sizeof(*snatm) || 511 (npcb->npcb_flags & NPCB_FREE) == 0) { 512 error = EINVAL; 513 break; 514 } 515 if (snatm->snatm_family != AF_NATM) { 516 error = EAFNOSUPPORT; 517 break; 518 } 519 520 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination 521 since ifunit() uses strcmp */ 522 523 /* 524 * convert interface string to ifp, validate. 525 */ 526 527 ifp = ifunit(snatm->snatm_if); 528 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { 529 error = ENXIO; 530 break; 531 } 532 if (ifp->if_output != atm_output) { 533 error = EAFNOSUPPORT; 534 break; 535 } 536 537 538 /* 539 * register us with the NATM PCB layer 540 */ 541 542 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { 543 error = EADDRINUSE; 544 break; 545 } 546 547 /* 548 * enable rx 549 */ 550 551 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 552 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 553 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 554 api.rxhand = npcb; 555 s2 = splimp(); 556 if (ifp->if_ioctl == NULL || 557 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) { 558 splx(s2); 559 npcb_free(npcb, NPCB_REMOVE); 560 error = EIO; 561 break; 562 } 563 splx(s2); 564 565 soisconnected(so); 566 567 break; 568 569 case PRU_DISCONNECT: /* disconnect from peer */ 570 571 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 572 printf("natm: disconnected check\n"); 573 error = EIO; 574 break; 575 } 576 ifp = npcb->npcb_ifp; 577 578 /* 579 * disable rx 580 */ 581 582 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 583 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 584 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 585 api.rxhand = npcb; 586 s2 = splimp(); 587 if (ifp->if_ioctl != NULL) 588 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 589 splx(s2); 590 591 npcb_free(npcb, NPCB_REMOVE); 592 soisdisconnected(so); 593 594 break; 595 596 case PRU_SHUTDOWN: /* won't send any more data */ 597 socantsendmore(so); 598 break; 599 600 case PRU_SEND: /* send this data */ 601 if (control && control->m_len) { 602 m_freem(control); 603 m_freem(m); 604 error = EINVAL; 605 break; 606 } 607 608 /* 609 * send the data. we must put an atm_pseudohdr on first 610 */ 611 612 M_PREPEND(m, sizeof(*aph), M_WAITOK); 613 if (m == NULL) { 614 error = ENOBUFS; 615 break; 616 } 617 aph = mtod(m, struct atm_pseudohdr *); 618 ATM_PH_VPI(aph) = npcb->npcb_vpi; 619 ATM_PH_SETVCI(aph, npcb->npcb_vci); 620 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 621 622 error = atm_output(npcb->npcb_ifp, m, NULL, NULL); 623 624 break; 625 626 case PRU_SENSE: /* return status into m */ 627 /* return zero? */ 628 break; 629 630 case PRU_PEERADDR: /* fetch peer's address */ 631 snatm = mtod(nam, struct sockaddr_natm *); 632 bzero(snatm, sizeof(*snatm)); 633 nam->m_len = snatm->snatm_len = sizeof(*snatm); 634 snatm->snatm_family = AF_NATM; 635#if defined(__NetBSD__) || defined(__OpenBSD__) 636 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if)); 637#elif defined(__FreeBSD__) 638 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name, 639 npcb->npcb_ifp->if_unit); 640#endif 641 snatm->snatm_vci = npcb->npcb_vci; 642 snatm->snatm_vpi = npcb->npcb_vpi; 643 break; 644 645 case PRU_CONTROL: /* control operations on protocol */ 646 /* 647 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 648 * SIOCXRAWATM and pass it to the driver. 649 */ 650 if ((u_long)m == SIOCRAWATM) { 651 if (npcb->npcb_ifp == NULL) { 652 error = ENOTCONN; 653 break; 654 } 655 ario.npcb = npcb; 656 ario.rawvalue = *((int *)nam); 657 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 658 SIOCXRAWATM, (caddr_t) &ario); 659 if (!error) { 660 if (ario.rawvalue) 661 npcb->npcb_flags |= NPCB_RAW; 662 else 663 npcb->npcb_flags &= ~(NPCB_RAW); 664 } 665 666 break; 667 } 668 669 error = EOPNOTSUPP; 670 break; 671 672 case PRU_BIND: /* bind socket to address */ 673 case PRU_LISTEN: /* listen for connection */ 674 case PRU_ACCEPT: /* accept connection from peer */ 675 case PRU_CONNECT2: /* connect two sockets */ 676 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */ 677 /* (only happens if LISTEN socket) */ 678 case PRU_RCVD: /* have taken data; more room now */ 679 case PRU_FASTTIMO: /* 200ms timeout */ 680 case PRU_SLOWTIMO: /* 500ms timeout */ 681 case PRU_RCVOOB: /* retrieve out of band data */ 682 case PRU_SENDOOB: /* send out of band data */ 683 case PRU_PROTORCV: /* receive from below */ 684 case PRU_PROTOSEND: /* send to below */ 685 case PRU_SOCKADDR: /* fetch socket's address */ 686#ifdef DIAGNOSTIC 687 printf("natm: PRU #%d unsupported\n", req); 688#endif 689 error = EOPNOTSUPP; 690 break; 691 692 default: panic("natm usrreq"); 693 } 694 695done: 696 splx(s); 697 return(error); 698} 699 700#endif /* !FREEBSD_USRREQS */ 701 702/* 703 * natmintr: splsoftnet interrupt 704 * 705 * note: we expect a socket pointer in rcvif rather than an interface 706 * pointer. we can get the interface pointer from the so's PCB if 707 * we really need it. 708 */ 709 710void 711natmintr() 712 713{ 714 int s; 715 struct mbuf *m; 716 struct socket *so; 717 struct natmpcb *npcb; 718 719next: 720 s = splimp(); 721 IF_DEQUEUE(&natmintrq, m); 722 splx(s); 723 if (m == NULL) 724 return; 725 726#ifdef DIAGNOSTIC 727 if ((m->m_flags & M_PKTHDR) == 0) 728 panic("natmintr no HDR"); 729#endif 730 731 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ 732 so = npcb->npcb_socket; 733 734 s = splimp(); /* could have atm devs @ different levels */ 735 npcb->npcb_inq--; 736 splx(s); 737 738 if (npcb->npcb_flags & NPCB_DRAIN) { 739 m_freem(m); 740 if (npcb->npcb_inq == 0) 741 FREE(npcb, M_PCB); /* done! */ 742 goto next; 743 } 744 745 if (npcb->npcb_flags & NPCB_FREE) { 746 m_freem(m); /* drop */ 747 goto next; 748 } 749 750#ifdef NEED_TO_RESTORE_IFP 751 m->m_pkthdr.rcvif = npcb->npcb_ifp; 752#else 753#ifdef DIAGNOSTIC 754m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ 755#endif 756#endif 757 758 if (sbspace(&so->so_rcv) > m->m_pkthdr.len || 759 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { 760#ifdef NATM_STAT 761 natm_sookcnt++; 762 natm_sookbytes += m->m_pkthdr.len; 763#endif 764 sbappendrecord(&so->so_rcv, m); 765 sorwakeup(so); 766 } else { 767#ifdef NATM_STAT 768 natm_sodropcnt++; 769 natm_sodropbytes += m->m_pkthdr.len; 770#endif 771 m_freem(m); 772 } 773 774 goto next; 775} 776 777#if defined(__FreeBSD__) 778NETISR_SET(NETISR_NATM, natmintr); 779#endif 780 781 782/* 783 * natm0_sysctl: not used, but here in case we want to add something 784 * later... 785 */ 786 787int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 788 789int *name; 790u_int namelen; 791void *oldp; 792size_t *oldlenp; 793void *newp; 794size_t newlen; 795 796{ 797 /* All sysctl names at this level are terminal. */ 798 if (namelen != 1) 799 return (ENOTDIR); 800 return (ENOPROTOOPT); 801} 802 803/* 804 * natm5_sysctl: not used, but here in case we want to add something 805 * later... 806 */ 807 808int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 809 810int *name; 811u_int namelen; 812void *oldp; 813size_t *oldlenp; 814void *newp; 815size_t newlen; 816 817{ 818 /* All sysctl names at this level are terminal. */ 819 if (namelen != 1) 820 return (ENOTDIR); 821 return (ENOPROTOOPT); 822}
| 415{ 416 return EOPNOTSUPP; 417} 418 419/* xxx - should be const */ 420struct pr_usrreqs natm_usrreqs = { 421 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind, 422 natm_usr_connect, pru_connect2_notsupp, natm_usr_control, 423 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp, 424 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, 425 natm_usr_send, pru_sense_null, natm_usr_shutdown, 426 natm_usr_sockaddr, sosend, soreceive, soselect 427}; 428 429#else /* !FREEBSD_USRREQS */ 430 431#if defined(__NetBSD__) || defined(__OpenBSD__) 432int natm_usrreq(so, req, m, nam, control, p) 433#elif defined(__FreeBSD__) 434int natm_usrreq(so, req, m, nam, control) 435#endif 436 437struct socket *so; 438int req; 439struct mbuf *m, *nam, *control; 440#if defined(__NetBSD__) || defined(__OpenBSD__) 441struct proc *p; 442#endif 443 444{ 445 int error = 0, s, s2; 446 struct natmpcb *npcb; 447 struct sockaddr_natm *snatm; 448 struct atm_pseudoioctl api; 449 struct atm_pseudohdr *aph; 450 struct atm_rawioctl ario; 451 struct ifnet *ifp; 452 int proto = so->so_proto->pr_protocol; 453 454 s = SPLSOFTNET(); 455 456 npcb = (struct natmpcb *) so->so_pcb; 457 458 if (npcb == NULL && req != PRU_ATTACH) { 459 error = EINVAL; 460 goto done; 461 } 462 463 464 switch (req) { 465 case PRU_ATTACH: /* attach protocol to up */ 466 467 if (npcb) { 468 error = EISCONN; 469 break; 470 } 471 472 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 473 if (proto == PROTO_NATMAAL5) 474 error = soreserve(so, natm5_sendspace, natm5_recvspace); 475 else 476 error = soreserve(so, natm0_sendspace, natm0_recvspace); 477 if (error) 478 break; 479 } 480 481 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK)); 482 npcb->npcb_socket = so; 483 484 break; 485 486 case PRU_DETACH: /* detach protocol from up */ 487 488 /* 489 * we turn on 'drain' *before* we sofree. 490 */ 491 492 npcb_free(npcb, NPCB_DESTROY); /* drain */ 493 so->so_pcb = NULL; 494 sofree(so); 495 496 break; 497 498 case PRU_CONNECT: /* establish connection to peer */ 499 500 /* 501 * validate nam and npcb 502 */ 503 504 if (nam->m_len != sizeof(*snatm)) { 505 error = EINVAL; 506 break; 507 } 508 snatm = mtod(nam, struct sockaddr_natm *); 509 if (snatm->snatm_len != sizeof(*snatm) || 510 (npcb->npcb_flags & NPCB_FREE) == 0) { 511 error = EINVAL; 512 break; 513 } 514 if (snatm->snatm_family != AF_NATM) { 515 error = EAFNOSUPPORT; 516 break; 517 } 518 519 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination 520 since ifunit() uses strcmp */ 521 522 /* 523 * convert interface string to ifp, validate. 524 */ 525 526 ifp = ifunit(snatm->snatm_if); 527 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { 528 error = ENXIO; 529 break; 530 } 531 if (ifp->if_output != atm_output) { 532 error = EAFNOSUPPORT; 533 break; 534 } 535 536 537 /* 538 * register us with the NATM PCB layer 539 */ 540 541 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) { 542 error = EADDRINUSE; 543 break; 544 } 545 546 /* 547 * enable rx 548 */ 549 550 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 551 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 552 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 553 api.rxhand = npcb; 554 s2 = splimp(); 555 if (ifp->if_ioctl == NULL || 556 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) { 557 splx(s2); 558 npcb_free(npcb, NPCB_REMOVE); 559 error = EIO; 560 break; 561 } 562 splx(s2); 563 564 soisconnected(so); 565 566 break; 567 568 case PRU_DISCONNECT: /* disconnect from peer */ 569 570 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { 571 printf("natm: disconnected check\n"); 572 error = EIO; 573 break; 574 } 575 ifp = npcb->npcb_ifp; 576 577 /* 578 * disable rx 579 */ 580 581 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; 582 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; 583 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); 584 api.rxhand = npcb; 585 s2 = splimp(); 586 if (ifp->if_ioctl != NULL) 587 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api); 588 splx(s2); 589 590 npcb_free(npcb, NPCB_REMOVE); 591 soisdisconnected(so); 592 593 break; 594 595 case PRU_SHUTDOWN: /* won't send any more data */ 596 socantsendmore(so); 597 break; 598 599 case PRU_SEND: /* send this data */ 600 if (control && control->m_len) { 601 m_freem(control); 602 m_freem(m); 603 error = EINVAL; 604 break; 605 } 606 607 /* 608 * send the data. we must put an atm_pseudohdr on first 609 */ 610 611 M_PREPEND(m, sizeof(*aph), M_WAITOK); 612 if (m == NULL) { 613 error = ENOBUFS; 614 break; 615 } 616 aph = mtod(m, struct atm_pseudohdr *); 617 ATM_PH_VPI(aph) = npcb->npcb_vpi; 618 ATM_PH_SETVCI(aph, npcb->npcb_vci); 619 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; 620 621 error = atm_output(npcb->npcb_ifp, m, NULL, NULL); 622 623 break; 624 625 case PRU_SENSE: /* return status into m */ 626 /* return zero? */ 627 break; 628 629 case PRU_PEERADDR: /* fetch peer's address */ 630 snatm = mtod(nam, struct sockaddr_natm *); 631 bzero(snatm, sizeof(*snatm)); 632 nam->m_len = snatm->snatm_len = sizeof(*snatm); 633 snatm->snatm_family = AF_NATM; 634#if defined(__NetBSD__) || defined(__OpenBSD__) 635 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if)); 636#elif defined(__FreeBSD__) 637 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name, 638 npcb->npcb_ifp->if_unit); 639#endif 640 snatm->snatm_vci = npcb->npcb_vci; 641 snatm->snatm_vpi = npcb->npcb_vpi; 642 break; 643 644 case PRU_CONTROL: /* control operations on protocol */ 645 /* 646 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to 647 * SIOCXRAWATM and pass it to the driver. 648 */ 649 if ((u_long)m == SIOCRAWATM) { 650 if (npcb->npcb_ifp == NULL) { 651 error = ENOTCONN; 652 break; 653 } 654 ario.npcb = npcb; 655 ario.rawvalue = *((int *)nam); 656 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 657 SIOCXRAWATM, (caddr_t) &ario); 658 if (!error) { 659 if (ario.rawvalue) 660 npcb->npcb_flags |= NPCB_RAW; 661 else 662 npcb->npcb_flags &= ~(NPCB_RAW); 663 } 664 665 break; 666 } 667 668 error = EOPNOTSUPP; 669 break; 670 671 case PRU_BIND: /* bind socket to address */ 672 case PRU_LISTEN: /* listen for connection */ 673 case PRU_ACCEPT: /* accept connection from peer */ 674 case PRU_CONNECT2: /* connect two sockets */ 675 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */ 676 /* (only happens if LISTEN socket) */ 677 case PRU_RCVD: /* have taken data; more room now */ 678 case PRU_FASTTIMO: /* 200ms timeout */ 679 case PRU_SLOWTIMO: /* 500ms timeout */ 680 case PRU_RCVOOB: /* retrieve out of band data */ 681 case PRU_SENDOOB: /* send out of band data */ 682 case PRU_PROTORCV: /* receive from below */ 683 case PRU_PROTOSEND: /* send to below */ 684 case PRU_SOCKADDR: /* fetch socket's address */ 685#ifdef DIAGNOSTIC 686 printf("natm: PRU #%d unsupported\n", req); 687#endif 688 error = EOPNOTSUPP; 689 break; 690 691 default: panic("natm usrreq"); 692 } 693 694done: 695 splx(s); 696 return(error); 697} 698 699#endif /* !FREEBSD_USRREQS */ 700 701/* 702 * natmintr: splsoftnet interrupt 703 * 704 * note: we expect a socket pointer in rcvif rather than an interface 705 * pointer. we can get the interface pointer from the so's PCB if 706 * we really need it. 707 */ 708 709void 710natmintr() 711 712{ 713 int s; 714 struct mbuf *m; 715 struct socket *so; 716 struct natmpcb *npcb; 717 718next: 719 s = splimp(); 720 IF_DEQUEUE(&natmintrq, m); 721 splx(s); 722 if (m == NULL) 723 return; 724 725#ifdef DIAGNOSTIC 726 if ((m->m_flags & M_PKTHDR) == 0) 727 panic("natmintr no HDR"); 728#endif 729 730 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ 731 so = npcb->npcb_socket; 732 733 s = splimp(); /* could have atm devs @ different levels */ 734 npcb->npcb_inq--; 735 splx(s); 736 737 if (npcb->npcb_flags & NPCB_DRAIN) { 738 m_freem(m); 739 if (npcb->npcb_inq == 0) 740 FREE(npcb, M_PCB); /* done! */ 741 goto next; 742 } 743 744 if (npcb->npcb_flags & NPCB_FREE) { 745 m_freem(m); /* drop */ 746 goto next; 747 } 748 749#ifdef NEED_TO_RESTORE_IFP 750 m->m_pkthdr.rcvif = npcb->npcb_ifp; 751#else 752#ifdef DIAGNOSTIC 753m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ 754#endif 755#endif 756 757 if (sbspace(&so->so_rcv) > m->m_pkthdr.len || 758 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { 759#ifdef NATM_STAT 760 natm_sookcnt++; 761 natm_sookbytes += m->m_pkthdr.len; 762#endif 763 sbappendrecord(&so->so_rcv, m); 764 sorwakeup(so); 765 } else { 766#ifdef NATM_STAT 767 natm_sodropcnt++; 768 natm_sodropbytes += m->m_pkthdr.len; 769#endif 770 m_freem(m); 771 } 772 773 goto next; 774} 775 776#if defined(__FreeBSD__) 777NETISR_SET(NETISR_NATM, natmintr); 778#endif 779 780 781/* 782 * natm0_sysctl: not used, but here in case we want to add something 783 * later... 784 */ 785 786int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 787 788int *name; 789u_int namelen; 790void *oldp; 791size_t *oldlenp; 792void *newp; 793size_t newlen; 794 795{ 796 /* All sysctl names at this level are terminal. */ 797 if (namelen != 1) 798 return (ENOTDIR); 799 return (ENOPROTOOPT); 800} 801 802/* 803 * natm5_sysctl: not used, but here in case we want to add something 804 * later... 805 */ 806 807int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 808 809int *name; 810u_int namelen; 811void *oldp; 812size_t *oldlenp; 813void *newp; 814size_t newlen; 815 816{ 817 /* All sysctl names at this level are terminal. */ 818 if (namelen != 1) 819 return (ENOTDIR); 820 return (ENOPROTOOPT); 821}
|