File:  [DragonFly] / src / sys / netproto / natm / natm.c
Revision 1.15: download - view: text, annotated - select for diffs
Fri Apr 9 22:34:10 2004 UTC (10 years, 7 months ago) by hsu
Branches: MAIN
CVS tags: HEAD
Push the lwkt_replymsg() up one level from netisr_service_loop() to
the message handler so we can explicitly reply or not reply as appropriate.

    1: /*	$NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $	*/
    2: /* $FreeBSD: src/sys/netnatm/natm.c,v 1.12 2000/02/13 03:32:03 peter Exp $ */
    3: /* $DragonFly: src/sys/netproto/natm/natm.c,v 1.15 2004/04/09 22:34:10 hsu Exp $ */
    4: 
    5: /*
    6:  *
    7:  * Copyright (c) 1996 Charles D. Cranor and Washington University.
    8:  * All rights reserved.
    9:  *
   10:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  * 3. All advertising materials mentioning features or use of this software
   19:  *    must display the following acknowledgement:
   20:  *      This product includes software developed by Charles D. Cranor and
   21:  *      Washington University.
   22:  * 4. The name of the author may not be used to endorse or promote products
   23:  *    derived from this software without specific prior written permission.
   24:  *
   25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   27:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   28:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   29:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   30:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   31:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   32:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35:  */
   36: 
   37: /*
   38:  * natm.c: native mode ATM access (both aal0 and aal5).
   39:  */
   40: 
   41: #include <sys/param.h>
   42: #include <sys/systm.h>
   43: #include <sys/kernel.h>
   44: #include <sys/proc.h>
   45: #include <sys/sockio.h>
   46: #include <sys/protosw.h>
   47: #include <sys/malloc.h>
   48: #include <sys/mbuf.h>
   49: #include <sys/socket.h>
   50: #include <sys/socketvar.h>
   51: 
   52: #include <sys/thread2.h>
   53: #include <sys/msgport2.h>
   54: 
   55: #include <net/if.h>
   56: #include <net/if_atm.h>
   57: #include <net/netisr.h>
   58: 
   59: #include <netinet/in.h>
   60: 
   61: #include "natm.h"
   62: 
   63: static u_long natm5_sendspace = 16*1024;
   64: static u_long natm5_recvspace = 16*1024;
   65: 
   66: static u_long natm0_sendspace = 16*1024;
   67: static u_long natm0_recvspace = 16*1024;
   68: 
   69: /*
   70:  * user requests
   71:  */
   72: #ifdef FREEBSD_USRREQS
   73: /*
   74:  * FreeBSD new usrreqs supersedes pr_usrreq.
   75:  */
   76: static int natm_usr_attach (struct socket *, int, struct pru_attach_info *);
   77: static int natm_usr_detach (struct socket *);
   78: static int natm_usr_connect (struct socket *, struct sockaddr *,
   79: 				 struct thread *);
   80: static int natm_usr_disconnect (struct socket *);
   81: static int natm_usr_shutdown (struct socket *);
   82: static int natm_usr_send (struct socket *, int, struct mbuf *,
   83: 			      struct sockaddr *, struct mbuf *, 
   84: 			      struct thread *);
   85: static int natm_usr_peeraddr (struct socket *, struct sockaddr **);
   86: static int natm_usr_control (struct socket *, u_long, caddr_t,
   87: 				 struct ifnet *, struct thread *);
   88: static int natm_usr_abort (struct socket *);
   89: static int natm_usr_bind (struct socket *, struct sockaddr *, 
   90: 			      struct thread *);
   91: static int natm_usr_sockaddr (struct socket *, struct sockaddr **);
   92: 
   93: static int
   94: natm_usr_attach(struct socket *so, int proto, struct pru_attach_info *ai)
   95: {
   96:     struct natmpcb *npcb;
   97:     int error = 0;
   98:     int s = SPLSOFTNET();
   99: 
  100:     npcb = (struct natmpcb *) so->so_pcb;
  101: 
  102:     if (npcb) {
  103: 	error = EISCONN;
  104: 	goto out;
  105:     }
  106: 
  107:     if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  108: 	if (proto == PROTO_NATMAAL5) 
  109: 	    error = soreserve(so, natm5_sendspace, natm5_recvspace,
  110: 			      ai->sb_rlimit);
  111: 	else
  112: 	    error = soreserve(so, natm0_sendspace, natm0_recvspace,
  113: 			      ai->sb_rlimit);
  114:         if (error)
  115:           goto out;
  116:     }
  117: 
  118:     so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  119:     npcb->npcb_socket = so;
  120:  out:
  121:     splx(s);
  122:     return (error);
  123: }
  124: 
  125: static int
  126: natm_usr_detach(struct socket *so)
  127: {
  128:     struct natmpcb *npcb;
  129:     int error = 0;
  130:     int s = SPLSOFTNET();
  131: 
  132:     npcb = (struct natmpcb *) so->so_pcb;
  133:     if (npcb == NULL) {
  134: 	error = EINVAL;
  135: 	goto out;
  136:     }
  137: 
  138:     /*
  139:      * we turn on 'drain' *before* we sofree.
  140:      */
  141:     npcb_free(npcb, NPCB_DESTROY);	/* drain */
  142:     so->so_pcb = NULL;
  143:     sofree(so);
  144:  out:
  145:     splx(s);
  146:     return (error);
  147: }
  148: 
  149: static int
  150: natm_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
  151: {
  152:     struct natmpcb *npcb;
  153:     struct sockaddr_natm *snatm;
  154:     struct atm_pseudoioctl api;
  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: 
  170:     snatm = (struct sockaddr_natm *)nam;
  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,
  218: 		      td->td_proc->p_ucred) != 0) {
  219: 	splx(s2);
  220: 	npcb_free(npcb, NPCB_REMOVE);
  221:         error = EIO;
  222: 	goto out;
  223:     }
  224:     splx(s2);
  225: 
  226:     soisconnected(so);
  227: 
  228:  out:
  229:     splx(s);
  230:     return (error);
  231: }
  232: 
  233: static int
  234: natm_usr_disconnect(struct socket *so)
  235: {
  236:     struct natmpcb *npcb;
  237:     struct atm_pseudoioctl api;
  238:     struct ifnet *ifp;
  239:     int error = 0;
  240:     int s2, s = SPLSOFTNET();
  241: 
  242:     npcb = (struct natmpcb *) so->so_pcb;
  243:     if (npcb == NULL) {
  244: 	error = EINVAL;
  245: 	goto out;
  246:     }
  247: 
  248:     if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
  249:         printf("natm: disconnected check\n");
  250:         error = EIO;
  251: 	goto out;
  252:     }
  253:     ifp = npcb->npcb_ifp;
  254: 
  255:     /*
  256:      * disable rx
  257:      */
  258: 
  259:     ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
  260:     ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  261:     ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  262:     api.rxhand = npcb;
  263:     s2 = splimp();
  264:     if (ifp->if_ioctl != NULL)
  265: 	ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api, (struct ucred *)NULL);
  266:     splx(s2);
  267: 
  268:     npcb_free(npcb, NPCB_REMOVE);
  269:     soisdisconnected(so);
  270: 
  271:  out:
  272:     splx(s);
  273:     return (error);
  274: }
  275: 
  276: static int
  277: natm_usr_shutdown(struct socket *so)
  278: {
  279:     socantsendmore(so);
  280:     return 0;
  281: }
  282: 
  283: static int
  284: natm_usr_send(struct socket *so, int flags, struct mbuf *m, 
  285: 	      struct sockaddr *nam, struct mbuf *control, struct thread *td)
  286: {
  287:     struct natmpcb *npcb;
  288:     struct atm_pseudohdr *aph;
  289:     int error = 0;
  290:     int s = SPLSOFTNET();
  291:     int proto = so->so_proto->pr_protocol;
  292: 
  293:     npcb = (struct natmpcb *) so->so_pcb;
  294:     if (npcb == NULL) {
  295: 	error = EINVAL;
  296: 	goto out;
  297:     }
  298: 
  299:     if (control && control->m_len) {
  300: 	m_freem(control);
  301: 	m_freem(m);
  302: 	error = EINVAL;
  303: 	goto out;
  304:     }
  305: 
  306:     /*
  307:      * send the data.   we must put an atm_pseudohdr on first
  308:      */
  309: 
  310:     M_PREPEND(m, sizeof(*aph), M_WAITOK);
  311:     if (m == NULL) {
  312:         error = ENOBUFS;
  313: 	goto out;
  314:     }
  315:     aph = mtod(m, struct atm_pseudohdr *);
  316:     ATM_PH_VPI(aph) = npcb->npcb_vpi;
  317:     ATM_PH_SETVCI(aph, npcb->npcb_vci);
  318:     ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  319: 
  320:     error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
  321: 
  322:  out:
  323:     splx(s);
  324:     return (error);
  325: }
  326: 
  327: static int
  328: natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
  329: {
  330:     struct natmpcb *npcb;
  331:     struct sockaddr_natm *snatm, ssnatm;
  332:     int error = 0;
  333:     int s = SPLSOFTNET();
  334: 
  335:     npcb = (struct natmpcb *) so->so_pcb;
  336:     if (npcb == NULL) {
  337: 	error = EINVAL;
  338: 	goto out;
  339:     }
  340: 
  341:     snatm = &ssnatm;
  342:     bzero(snatm, sizeof(*snatm));
  343:     snatm->snatm_len = sizeof(*snatm);
  344:     snatm->snatm_family = AF_NATM;
  345:     strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
  346:         sizeof(snatm->snatm_if));
  347:     snatm->snatm_vci = npcb->npcb_vci;
  348:     snatm->snatm_vpi = npcb->npcb_vpi;
  349:     *nam = dup_sockaddr((struct sockaddr *)snatm, 0);
  350: 
  351:  out:
  352:     splx(s);
  353:     return (error);
  354: }
  355: 
  356: static int
  357: natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
  358: 		 struct ifnet *ifp, struct thread *td)
  359: {
  360:     struct natmpcb *npcb;
  361:     struct atm_rawioctl ario;
  362:     int error = 0;
  363:     int s = SPLSOFTNET();
  364: 
  365:     npcb = (struct natmpcb *) so->so_pcb;
  366:     if (npcb == NULL) {
  367: 	error = EINVAL;
  368: 	goto out;
  369:     }
  370: 
  371:     /*
  372:      * raw atm ioctl.   comes in as a SIOCRAWATM.   we convert it to
  373:      * SIOCXRAWATM and pass it to the driver.
  374:      */
  375:     if (cmd == SIOCRAWATM) {
  376:         if (npcb->npcb_ifp == NULL) {
  377: 	    error = ENOTCONN;
  378: 	    goto out;
  379:         }
  380:         ario.npcb = npcb;
  381:         ario.rawvalue = *((int *)arg);
  382:         error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, 
  383: 					 SIOCXRAWATM, (caddr_t) &ario,
  384: 					 td->td_proc->p_ucred);
  385: 	if (!error) {
  386: 	    if (ario.rawvalue) 
  387: 		npcb->npcb_flags |= NPCB_RAW;
  388: 	    else
  389: 		npcb->npcb_flags &= ~(NPCB_RAW);
  390: 	}
  391:     }
  392:     else
  393: 	error = EOPNOTSUPP;
  394: 
  395:  out:
  396:     splx(s);
  397:     return (error);
  398: }
  399: 
  400: static int
  401: natm_usr_abort(struct socket *so)
  402: {
  403:     return natm_usr_shutdown(so);
  404: }
  405: 
  406: static int
  407: natm_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
  408: {
  409:     return EOPNOTSUPP;
  410: }
  411: 
  412: static int
  413: natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
  414: {
  415:     return EOPNOTSUPP;
  416: }
  417: 
  418: /* xxx - should be const */
  419: struct pr_usrreqs natm_usrreqs = {
  420: 	natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
  421: 	natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
  422: 	natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
  423: 	natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
  424: 	natm_usr_send, pru_sense_null, natm_usr_shutdown,
  425: 	natm_usr_sockaddr, sosend, soreceive, sopoll
  426: };
  427: 
  428: #else  /* !FREEBSD_USRREQS */
  429: 
  430: #if defined(__NetBSD__) || defined(__OpenBSD__)
  431: int natm_usrreq(so, req, m, nam, control, p)
  432: #elif defined(__DragonFly__)
  433: int natm_usrreq(so, req, m, nam, control)
  434: #endif
  435: 
  436: struct socket *so;
  437: int req;
  438: struct mbuf *m, *nam, *control;
  439: #if defined(__NetBSD__) || defined(__OpenBSD__)
  440: struct proc *p;
  441: #endif
  442: 
  443: {
  444:   int error = 0, s, s2;
  445:   struct natmpcb *npcb;
  446:   struct sockaddr_natm *snatm;
  447:   struct atm_pseudoioctl api;
  448:   struct atm_pseudohdr *aph;
  449:   struct atm_rawioctl ario;
  450:   struct ifnet *ifp;
  451:   int proto = so->so_proto->pr_protocol;
  452: 
  453:   s = SPLSOFTNET();
  454: 
  455:   npcb = (struct natmpcb *) so->so_pcb;
  456: 
  457:   if (npcb == NULL && req != PRU_ATTACH) {
  458:     error = EINVAL;
  459:     goto done;
  460:   }
  461:     
  462: 
  463:   switch (req) {
  464:     case PRU_ATTACH:			/* attach protocol to up */
  465: 
  466:       if (npcb) {
  467: 	error = EISCONN;
  468: 	break;
  469:       }
  470: 
  471:       if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  472: 	if (proto == PROTO_NATMAAL5) 
  473:           error = soreserve(so, natm5_sendspace, natm5_recvspace);
  474: 	else
  475:           error = soreserve(so, natm0_sendspace, natm0_recvspace);
  476:         if (error)
  477:           break;
  478:       }
  479: 
  480:       so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
  481:       npcb->npcb_socket = so;
  482: 
  483:       break;
  484: 
  485:     case PRU_DETACH:			/* detach protocol from up */
  486: 
  487:       /*
  488:        * we turn on 'drain' *before* we sofree.
  489:        */
  490: 
  491:       npcb_free(npcb, NPCB_DESTROY);	/* drain */
  492:       so->so_pcb = NULL;
  493:       sofree(so);
  494: 
  495:       break;
  496: 
  497:     case PRU_CONNECT:			/* establish connection to peer */
  498: 
  499:       /*
  500:        * validate nam and npcb
  501:        */
  502: 
  503:       if (nam->m_len != sizeof(*snatm)) {
  504:         error = EINVAL;
  505: 	break;
  506:       }
  507:       snatm = mtod(nam, struct sockaddr_natm *);
  508:       if (snatm->snatm_len != sizeof(*snatm) ||
  509: 		(npcb->npcb_flags & NPCB_FREE) == 0) {
  510: 	error = EINVAL;
  511: 	break;
  512:       }
  513:       if (snatm->snatm_family != AF_NATM) {
  514: 	error = EAFNOSUPPORT;
  515: 	break;
  516:       }
  517: 
  518:       snatm->snatm_if[IFNAMSIZ-1] = '\0';  /* XXX ensure null termination
  519: 						since ifunit() uses strcmp */
  520: 
  521:       /*
  522:        * convert interface string to ifp, validate.
  523:        */
  524: 
  525:       ifp = ifunit(snatm->snatm_if);
  526:       if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
  527: 	error = ENXIO;
  528: 	break;
  529:       }
  530:       if (ifp->if_output != atm_output) {
  531: 	error = EAFNOSUPPORT;
  532: 	break;
  533:       }
  534: 
  535: 
  536:       /*
  537:        * register us with the NATM PCB layer
  538:        */
  539: 
  540:       if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
  541:         error = EADDRINUSE;
  542:         break;
  543:       }
  544: 
  545:       /*
  546:        * enable rx
  547:        */
  548: 
  549:       ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
  550:       ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
  551:       ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
  552:       api.rxhand = npcb;
  553:       s2 = splimp();
  554:       if (ifp->if_ioctl == NULL || 
  555: 	  ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api,
  556: 	  		(struct ucred *)NULL) != 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, (struct ucred *)NULL);
  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__) || defined(__DragonFly__)
  635:       bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
  636: #elif defined(__DragonFly__)
  637:       snprintf(snatm->snatm_if, sizeof(snatm->snatm_if),
  638: 	"%s%d", npcb->npcb_ifp->if_name, 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, SIOCXRAWATM,
  657:         				 (caddr_t) &ario, (struct ucred *)NULL);
  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: 
  694: done:
  695:   splx(s);
  696:   return(error);
  697: }
  698: 
  699: #endif  /* !FREEBSD_USRREQS */
  700: 
  701: /* 
  702:  * natm0_sysctl: not used, but here in case we want to add something
  703:  * later...
  704:  */
  705: 
  706: int natm0_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
  707:     void *newp, size_t newlen)
  708: {
  709:   /* All sysctl names at this level are terminal. */
  710:   if (namelen != 1)
  711:     return (ENOTDIR);
  712:   return (ENOPROTOOPT);
  713: }
  714: 
  715: /* 
  716:  * natm5_sysctl: not used, but here in case we want to add something
  717:  * later...
  718:  */
  719: 
  720: int natm5_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
  721:     void *newp, size_t newlen)
  722: {
  723:   /* All sysctl names at this level are terminal. */
  724:   if (namelen != 1)
  725:     return (ENOTDIR);
  726:   return (ENOPROTOOPT);
  727: }
  728: 
  729: static void natmintr(struct netmsg *);
  730: 
  731: #if defined(__DragonFly__)
  732: static void
  733: netisr_natm_setup(void *dummy __unused)
  734: {
  735: 
  736: 	netisr_register(NETISR_NATM, cpu0_portfn, natmintr);
  737: }
  738: SYSINIT(natm_setup, SI_SUB_CPU, SI_ORDER_ANY, netisr_natm_setup, NULL);
  739: #endif
  740: 
  741: void
  742: natm_init()
  743: {
  744:   LIST_INIT(&natm_pcbs);
  745: 
  746:   netisr_register(NETISR_NATM, cpu0_portfn, natmintr);
  747: }
  748: 
  749: /*
  750:  * natmintr: splsoftnet interrupt
  751:  *
  752:  * note: we expect a socket pointer in rcvif rather than an interface
  753:  * pointer.    we can get the interface pointer from the so's PCB if
  754:  * we really need it.
  755:  */
  756: static void
  757: natmintr(struct netmsg *msg)
  758: {
  759:   struct mbuf *m = ((struct netmsg_packet *)msg)->nm_packet;
  760:   int s;
  761:   struct socket *so;
  762:   struct natmpcb *npcb;
  763: 
  764: #ifdef DIAGNOSTIC
  765:   if ((m->m_flags & M_PKTHDR) == 0)
  766:     panic("natmintr no HDR");
  767: #endif
  768: 
  769:   npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
  770:   so = npcb->npcb_socket;
  771: 
  772:   s = splimp();			/* could have atm devs @ different levels */
  773:   npcb->npcb_inq--;
  774:   splx(s);
  775: 
  776:   if (npcb->npcb_flags & NPCB_DRAIN) {
  777:     m_freem(m);
  778:     if (npcb->npcb_inq == 0)
  779:       FREE(npcb, M_PCB);			/* done! */
  780:     goto out;
  781:   }
  782: 
  783:   if (npcb->npcb_flags & NPCB_FREE) {
  784:     m_freem(m);					/* drop */
  785:     goto out;
  786:   }
  787: 
  788: #ifdef NEED_TO_RESTORE_IFP
  789:   m->m_pkthdr.rcvif = npcb->npcb_ifp;
  790: #else
  791: #ifdef DIAGNOSTIC
  792: m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
  793: #endif
  794: #endif
  795: 
  796:   if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
  797:      ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
  798: #ifdef NATM_STAT
  799:     natm_sookcnt++;
  800:     natm_sookbytes += m->m_pkthdr.len;
  801: #endif
  802:     sbappendrecord(&so->so_rcv, m);
  803:     sorwakeup(so);
  804:   } else {
  805: #ifdef NATM_STAT
  806:     natm_sodropcnt++;
  807:     natm_sodropbytes += m->m_pkthdr.len;
  808: #endif
  809:     m_freem(m);
  810:   }
  811: out:
  812:   lwkt_replymsg(&msg->nm_lmsg, 0);
  813: }
  814: