The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netatm/atm_cm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * ===================================
    3  * HARP  |  Host ATM Research Platform
    4  * ===================================
    5  *
    6  *
    7  * This Host ATM Research Platform ("HARP") file (the "Software") is
    8  * made available by Network Computing Services, Inc. ("NetworkCS")
    9  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   10  * support of any kind.
   11  *
   12  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   13  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   14  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   15  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   16  * In no event shall NetworkCS be responsible for any damages, including
   17  * but not limited to consequential damages, arising from or relating to
   18  * any use of the Software or related support.
   19  *
   20  * Copyright 1994-1998 Network Computing Services, Inc.
   21  *
   22  * Copies of this Software may be made, however, the above copyright
   23  * notice must be reproduced on all copies.
   24  */
   25 
   26 /*
   27  * Core ATM Services
   28  * -----------------
   29  *
   30  * ATM Connection Manager
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/5.2/sys/netatm/atm_cm.c 118060 2003-07-26 14:20:37Z harti $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/errno.h>
   39 #include <sys/time.h>
   40 #include <sys/socket.h>
   41 #include <sys/socketvar.h>
   42 #include <sys/syslog.h>
   43 #include <net/if.h>
   44 #include <net/bpf.h>
   45 #include <netatm/port.h>
   46 #include <netatm/queue.h>
   47 #include <netatm/atm.h>
   48 #include <netatm/atm_sys.h>
   49 #include <netatm/atm_sap.h>
   50 #include <netatm/atm_cm.h>
   51 #include <netatm/atm_if.h>
   52 #include <netatm/atm_vc.h>
   53 #include <netatm/atm_sigmgr.h>
   54 #include <netatm/atm_stack.h>
   55 #include <netatm/atm_pcb.h>
   56 #include <netatm/atm_var.h>
   57 
   58 /*
   59  * Global variables
   60  */
   61 struct atm_cm_stat      atm_cm_stat = {0};
   62 
   63 /*
   64  * Local functions
   65  */
   66 static void             atm_cm_cpcs_upper(int, void *, intptr_t, intptr_t);
   67 static void             atm_cm_saal_upper(int, void *, intptr_t, intptr_t);
   68 static void             atm_cm_sscop_upper(int, void *, intptr_t, intptr_t);
   69 static Atm_connvc *     atm_cm_share_llc(Atm_attributes *);
   70 static void             atm_cm_closeconn(Atm_connection *,
   71                                 struct t_atm_cause *);
   72 static void             atm_cm_closevc(Atm_connvc *);
   73 static void             atm_cm_timeout(struct atm_time *);
   74 static KTimeout_ret     atm_cm_procinq(void *);
   75 static void             atm_cm_incall(Atm_connvc *);
   76 static int              atm_cm_accept(Atm_connvc *, Atm_connection *);
   77 
   78 /*
   79  * Local variables
   80  */
   81 static Queue_t          atm_connection_queue = {NULL};
   82 static Queue_t          atm_incoming_queue = {NULL};
   83 static int              atm_incoming_qlen = 0;
   84 static Atm_connection   *atm_listen_queue = NULL;
   85 static struct attr_cause        atm_cause_tmpl = 
   86         {T_ATM_PRESENT, {T_ATM_ITU_CODING, T_ATM_LOC_USER, 0, {0, 0, 0, 0}}};
   87 
   88 /*
   89  * Stack commands, indexed by API
   90  */
   91 static struct {
   92         int             init;
   93         int             term;
   94 } atm_stackcmds[] = {
   95         {CPCS_INIT, CPCS_TERM},         /* CMAPI_CPCS */
   96         {SSCF_UNI_INIT, SSCF_UNI_TERM}, /* CMAPI_SAAL */
   97         {SSCOP_INIT, SSCOP_TERM},       /* CMAPI_SSCOP */
   98 };
   99 
  100 static uma_zone_t atm_connection_zone;
  101 static uma_zone_t atm_connvc_zone;
  102 
  103 void
  104 atm_cm_init(void)
  105 {
  106 
  107         atm_connection_zone = uma_zcreate("atm connection",
  108             sizeof(Atm_connection), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  109         if (atm_connection_zone == NULL)
  110                 panic("atm_connection_zone");
  111 
  112         atm_connvc_zone = uma_zcreate("atm connvc", sizeof(Atm_connvc), NULL,
  113             NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  114         if (atm_connvc_zone == NULL)
  115                 panic("atm_connvc_zone");
  116 }
  117 
  118 /*
  119  * Initiate Outgoing ATM Call
  120  * 
  121  * Called by an endpoint service to create a new Connection Manager API
  122  * instance and to initiate an outbound ATM connection.  The endpoint
  123  * provided token will be used in all further CM -> endpoint function
  124  * calls, and the returned connection block pointer must be used in all
  125  * subsequent endpoint -> CM function calls.
  126  *
  127  * If the return indicates that the connection setup has been immediately
  128  * successful (typically only for PVCs and shared SVCs), then the connection
  129  * is ready for data transmission.
  130  *
  131  * If the return indicates that the connection setup is still in progress,
  132  * then the endpoint must wait for notification from the Connection Manager
  133  * indicating the final status of the call setup.  If the call setup completes
  134  * successfully, then a "call connected" notification will be sent to the
  135  * endpoint by the Connection Manager.  If the call setup fails, then the
  136  * endpoint will receive a "call cleared" notification.
  137  *
  138  * All connection instances must be freed with an atm_cm_release() call.
  139  *
  140  * Arguments:
  141  *      epp     pointer to endpoint definition structure
  142  *      token   endpoint's connection instance token
  143  *      ap      pointer to requested connection attributes
  144  *      copp    pointer to location to return allocated connection block
  145  *
  146  * Returns:
  147  *      0       connection has been successfully established
  148  *      EINPROGRESS     connection establishment is in progress
  149  *      errno   connection failed - reason indicated
  150  *
  151  */
  152 int
  153 atm_cm_connect(epp, token, ap, copp)
  154         Atm_endpoint    *epp;
  155         void            *token;
  156         Atm_attributes  *ap;
  157         Atm_connection  **copp;
  158 {
  159         Atm_connection  *cop;
  160         Atm_connvc      *cvp;
  161         struct atm_pif  *pip;
  162         struct sigmgr   *smp;
  163         struct stack_list       sl;
  164         void            (*upf)(int, void *, intptr_t, intptr_t);
  165         int             s, sli, err, err2;
  166 
  167         *copp = NULL;
  168         cvp = NULL;
  169 
  170         /*
  171          * Get a connection block
  172          * May be called from timeout - don't wait.
  173          */
  174         cop = uma_zalloc(atm_connection_zone, M_NOWAIT);
  175         if (cop == NULL)
  176                 return (ENOMEM);
  177 
  178         /*
  179          * Initialize connection info
  180          */
  181         cop->co_endpt = epp;
  182         cop->co_toku = token;
  183 
  184         /*
  185          * Initialize stack list index
  186          */
  187         sli = 0;
  188 
  189         /*
  190          * Validate and extract useful attribute information
  191          */
  192 
  193         /*
  194          * Must specify a network interface (validated below)
  195          */
  196         if (ap->nif == NULL) {
  197                 err = EINVAL;
  198                 goto done;
  199         }
  200 
  201         /*
  202          * Check out Data API
  203          */
  204         switch (ap->api) {
  205 
  206         case CMAPI_CPCS:
  207                 upf = atm_cm_cpcs_upper;
  208                 break;
  209 
  210         case CMAPI_SAAL:
  211                 sl.sl_sap[sli++] = SAP_SSCF_UNI;
  212                 sl.sl_sap[sli++] = SAP_SSCOP;
  213                 upf = atm_cm_saal_upper;
  214                 break;
  215 
  216         case CMAPI_SSCOP:
  217                 sl.sl_sap[sli++] = SAP_SSCOP;
  218                 upf = atm_cm_sscop_upper;
  219                 break;
  220 
  221         default:
  222                 err = EINVAL;
  223                 goto done;
  224         }
  225 
  226         /*
  227          * AAL Attributes
  228          */
  229         if (ap->aal.tag != T_ATM_PRESENT) {
  230                 err = EINVAL;
  231                 goto done;
  232         }
  233 
  234         switch (ap->aal.type) {
  235 
  236         case ATM_AAL5:
  237                 sl.sl_sap[sli++] = SAP_CPCS_AAL5;
  238                 sl.sl_sap[sli++] = SAP_SAR_AAL5;
  239                 sl.sl_sap[sli++] = SAP_ATM;
  240                 break;
  241 
  242         case ATM_AAL3_4:
  243                 sl.sl_sap[sli++] = SAP_CPCS_AAL3_4;
  244                 sl.sl_sap[sli++] = SAP_SAR_AAL3_4;
  245                 sl.sl_sap[sli++] = SAP_ATM;
  246                 break;
  247 
  248         default:
  249                 err = EINVAL;
  250                 goto done;
  251         }
  252 
  253         /*
  254          * Broadband Bearer Attributes
  255          */
  256         if (ap->bearer.tag != T_ATM_PRESENT) {
  257                 err = EINVAL;
  258                 goto done;
  259         }
  260 
  261         switch (ap->bearer.v.connection_configuration) {
  262 
  263         case T_ATM_1_TO_1:
  264                 cop->co_flags |= COF_P2P;
  265                 break;
  266 
  267         case T_ATM_1_TO_MANY:
  268                 /* Not supported */
  269                 cop->co_flags |= COF_P2MP;
  270                 err = EINVAL;
  271                 goto done;
  272 
  273         default:
  274                 err = EINVAL;
  275                 goto done;
  276         }
  277 
  278         /*
  279          * Logical Link Control Attributes
  280          */
  281         if (ap->llc.tag == T_ATM_PRESENT) {
  282                 if ((ap->blli.tag_l2 != T_ATM_PRESENT) ||
  283                     (ap->blli.v.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) ||
  284                     (ap->blli.v.layer_2_protocol.ID.simple_ID != 
  285                                 T_ATM_BLLI2_I8802) ||
  286                     (ap->llc.v.llc_len < T_ATM_LLC_MIN_LEN) ||
  287                     (ap->llc.v.llc_len > T_ATM_LLC_MAX_LEN)) {
  288                         err = EINVAL;
  289                         goto done;
  290                 }
  291                 cop->co_mpx = ATM_ENC_LLC;
  292                 cop->co_llc = ap->llc;
  293         } else
  294                 cop->co_mpx = ATM_ENC_NULL;
  295 
  296         /*
  297          * Called Party Attributes
  298          */
  299         if (ap->called.tag != T_ATM_PRESENT) {
  300                 err = EINVAL;
  301                 goto done;
  302         }
  303 
  304         if ((ap->called.addr.address_format == T_ATM_ABSENT) ||
  305             (ap->called.addr.address_length == 0)) {
  306                 err = EINVAL;
  307                 goto done;
  308         }
  309 
  310         /*
  311          * Calling Party Attributes
  312          */
  313         if (ap->calling.tag != T_ATM_ABSENT) {
  314                 err = EINVAL;
  315                 goto done;
  316         }
  317 
  318         /*
  319          * Quality of Service Attributes
  320          */
  321         if (ap->qos.tag != T_ATM_PRESENT) {
  322                 err = EINVAL;
  323                 goto done;
  324         }
  325 
  326         /*
  327          * Terminate stack list 
  328          */
  329         sl.sl_sap[sli] = 0;
  330 
  331         s = splnet();
  332 
  333         /*
  334          * Let multiplexors decide whether we need a new VCC
  335          */
  336         switch (cop->co_mpx) {
  337 
  338         case ATM_ENC_NULL:
  339                 /*
  340                  * All of these connections require a new VCC
  341                  */
  342                 break;
  343 
  344         case ATM_ENC_LLC:
  345                 /*
  346                  * See if we can share an existing LLC connection
  347                  */
  348                 cvp = atm_cm_share_llc(ap);
  349                 if (cvp == NULL)
  350                         break;
  351 
  352                 /*
  353                  * We've got a connection to share
  354                  */
  355                 cop->co_connvc = cvp;
  356                 if (cvp->cvc_state == CVCS_ACTIVE) {
  357                         cop->co_state = COS_ACTIVE;
  358                         err = 0;
  359                 } else {
  360                         cop->co_state = COS_OUTCONN;
  361                         err = EINPROGRESS;
  362                 }
  363                 LINK2TAIL(cop, Atm_connection, cvp->cvc_conn->co_mxh, co_next);
  364                 cop->co_mxh = cvp->cvc_conn->co_mxh;
  365                 *copp = cop;
  366 
  367                 (void) splx(s);
  368                 return (err);
  369 
  370         default:
  371                 panic("atm_cm_connect: unknown mpx");
  372         }
  373 
  374         /*
  375          * If we get here, it means we need to create 
  376          * a new VCC for this connection
  377          */
  378 
  379         /*
  380          * Validate that network interface is registered and that 
  381          * a signalling manager is attached
  382          */
  383         for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
  384                 struct atm_nif  *nip;
  385                 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
  386                         if (nip == ap->nif)
  387                                 break;
  388                 }
  389                 if (nip)
  390                         break;
  391         }
  392         if (pip == NULL) {
  393                 err = ENXIO;
  394                 goto donex;
  395         }
  396 
  397         if ((smp = pip->pif_sigmgr) == NULL) {
  398                 err = ENXIO;
  399                 goto donex;
  400         }
  401 
  402         /*
  403          * Get a connection VCC block
  404          * May be called from timeouts - don't wait.
  405          */
  406         cvp = uma_zalloc(atm_connvc_zone, M_NOWAIT);
  407         if (cvp == NULL) {
  408                 err = ENOMEM;
  409                 goto donex;
  410         }
  411 
  412         /*
  413          * Save VCC attributes
  414          */
  415         cvp->cvc_attr = *ap;
  416         cvp->cvc_flags |= CVCF_CALLER;
  417 
  418         /*
  419          * Link the control blocks
  420          */
  421         cop->co_connvc = cvp;
  422         cvp->cvc_conn = cop;
  423         cvp->cvc_sigmgr = smp;
  424 
  425         /*
  426          * Create a service stack
  427          */
  428         err = atm_create_stack(cvp, &sl, upf);
  429         if (err) {
  430                 cvp->cvc_state = CVCS_CLEAR;
  431                 atm_cm_closevc(cvp);
  432                 goto donex;
  433         }
  434 
  435         /*
  436          * Let the signalling manager handle the VCC creation
  437          */
  438         cvp->cvc_state = CVCS_SETUP;
  439         switch ((*smp->sm_setup)(cvp, &err)) {
  440 
  441         case CALL_CONNECTED:
  442                 /*
  443                  * Connection is fully setup - initialize the stack
  444                  */
  445                 cvp->cvc_state = CVCS_INIT;
  446                 STACK_CALL(atm_stackcmds[ap->api].init, cvp->cvc_lower,
  447                         cvp->cvc_tokl, cvp, ap->api_init, 0, err2);
  448                 if (err2)
  449                         panic("atm_cm_connect: init");
  450 
  451                 if (cvp->cvc_flags & CVCF_ABORTING) {
  452                         /*
  453                          * Someone on the stack bailed out...schedule the 
  454                          * VCC and stack termination
  455                          */
  456                         atm_cm_closevc(cvp);
  457                         err = EFAULT;
  458                 } else {
  459                         /*
  460                          * Everything looks fine from here
  461                          */
  462                         cvp->cvc_state = CVCS_ACTIVE;
  463                         cop->co_state = COS_ACTIVE;
  464                 }
  465                 break;
  466 
  467         case CALL_FAILED:
  468                 /*
  469                  * Terminate stack and clean up before we leave
  470                  */
  471                 cvp->cvc_state = CVCS_CLEAR;
  472                 atm_cm_closevc(cvp);
  473                 break;
  474 
  475         case CALL_PROCEEDING:
  476                 /*
  477                  * We'll just wait for final call status
  478                  */
  479                 cop->co_state = COS_OUTCONN;
  480                 err = EINPROGRESS;
  481                 break;
  482 
  483         default:
  484                 panic("atm_cm_connect: setup");
  485         }
  486 
  487 donex:
  488         (void) splx(s);
  489 
  490 done:
  491         if (err && err != EINPROGRESS) {
  492                 /*
  493                  * Undo any partial setup stuff
  494                  */
  495                 if (cop)
  496                         uma_zfree(atm_connection_zone, cop);
  497         } else {
  498                 /*
  499                  * Finish connection setup
  500                  */
  501                 s = splnet();
  502                 cvp->cvc_flags |= CVCF_CONNQ;
  503                 ENQUEUE(cvp, Atm_connvc, cvc_q, atm_connection_queue);
  504                 LINK2TAIL(cop, Atm_connection, cop->co_mxh, co_next);
  505                 (void) splx(s);
  506                 *copp = cop;
  507         }
  508         return (err);
  509 }
  510 
  511 
  512 /*
  513  * Listen for Incoming ATM Calls
  514  * 
  515  * Called by an endpoint service in order to indicate its willingness to
  516  * accept certain incoming calls.  The types of calls which the endpoint
  517  * is prepared to accept are specified in the Atm_attributes parameter.
  518  *
  519  * For each call which meets the criteria specified by the endpoint, the
  520  * endpoint service will receive an incoming call notification via the
  521  * endpoint's ep_incoming() function.
  522  *
  523  * To cancel the listening connection, the endpoint user should invoke 
  524  * atm_cm_release().
  525  *
  526  * Arguments:
  527  *      epp     pointer to endpoint definition structure
  528  *      token   endpoint's listen instance token
  529  *      ap      pointer to listening connection attributes
  530  *      copp    pointer to location to return allocated connection block
  531  *
  532  * Returns:
  533  *      0       listening connection installed
  534  *      errno   listen failed - reason indicated
  535  *
  536  */
  537 int
  538 atm_cm_listen(epp, token, ap, copp)
  539         Atm_endpoint    *epp;
  540         void            *token;
  541         Atm_attributes  *ap;
  542         Atm_connection  **copp;
  543 {
  544         Atm_connection  *cop;
  545         int             s, err = 0;
  546 
  547         *copp = NULL;
  548 
  549         /*
  550          * Get a connection block
  551          */
  552         cop = uma_zalloc(atm_connection_zone, M_WAITOK);
  553         if (cop == NULL)
  554                 return (ENOMEM);
  555 
  556         /*
  557          * Initialize connection info
  558          */
  559         cop->co_endpt = epp;
  560         cop->co_toku = token;
  561         cop->co_mxh = cop;
  562 
  563         /*
  564          * Validate and extract useful attribute information
  565          */
  566 
  567         /*
  568          * Check out Data API
  569          */
  570         switch (ap->api) {
  571 
  572         case CMAPI_CPCS:
  573         case CMAPI_SAAL:
  574         case CMAPI_SSCOP:
  575                 break;
  576 
  577         default:
  578                 err = EINVAL;
  579                 goto done;
  580         }
  581 
  582         /*
  583          * AAL Attributes
  584          */
  585         switch (ap->aal.tag) {
  586 
  587         case T_ATM_PRESENT:
  588 
  589                 switch (ap->aal.type) {
  590 
  591                 case ATM_AAL5:
  592                 case ATM_AAL3_4:
  593                         break;
  594 
  595                 default:
  596                         err = EINVAL;
  597                         goto done;
  598                 }
  599                 break;
  600 
  601         case T_ATM_ABSENT:
  602         case T_ATM_ANY:
  603                 break;
  604 
  605         default:
  606                 err = EINVAL;
  607                 goto done;
  608         }
  609 
  610         /*
  611          * Broadband High Layer Information Attributes
  612          */
  613         switch (ap->bhli.tag) {
  614 
  615         case T_ATM_PRESENT:
  616         case T_ATM_ABSENT:
  617         case T_ATM_ANY:
  618                 break;
  619 
  620         default:
  621                 err = EINVAL;
  622                 goto done;
  623         }
  624 
  625         /*
  626          * Broadband Low Layer Information Attributes
  627          */
  628         switch (ap->blli.tag_l2) {
  629 
  630         case T_ATM_PRESENT:
  631         case T_ATM_ABSENT:
  632         case T_ATM_ANY:
  633                 break;
  634 
  635         default:
  636                 err = EINVAL;
  637                 goto done;
  638         }
  639 
  640         switch (ap->blli.tag_l3) {
  641 
  642         case T_ATM_PRESENT:
  643         case T_ATM_ABSENT:
  644         case T_ATM_ANY:
  645                 break;
  646 
  647         default:
  648                 err = EINVAL;
  649                 goto done;
  650         }
  651 
  652         /*
  653          * Logical Link Control Attributes
  654          */
  655         switch (ap->llc.tag) {
  656 
  657         case T_ATM_PRESENT:
  658                 if ((ap->blli.tag_l2 != T_ATM_PRESENT) ||
  659                     (ap->blli.v.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) ||
  660                     (ap->blli.v.layer_2_protocol.ID.simple_ID != 
  661                                 T_ATM_BLLI2_I8802) ||
  662                     (ap->llc.v.llc_len < T_ATM_LLC_MIN_LEN) ||
  663                     (ap->llc.v.llc_len > T_ATM_LLC_MAX_LEN)) {
  664                         err = EINVAL;
  665                         goto done;
  666                 }
  667                 cop->co_mpx = ATM_ENC_LLC;
  668                 cop->co_llc = ap->llc;
  669                 break;
  670 
  671         case T_ATM_ABSENT:
  672         case T_ATM_ANY:
  673                 cop->co_mpx = ATM_ENC_NULL;
  674                 break;
  675 
  676         default:
  677                 err = EINVAL;
  678                 goto done;
  679         }
  680 
  681         /*
  682          * Called Party Attributes
  683          */
  684         switch (ap->called.tag) {
  685 
  686         case T_ATM_PRESENT:
  687                 switch (ap->called.addr.address_format) {
  688 
  689                 case T_ATM_ABSENT:
  690                         ap->called.tag = T_ATM_ABSENT;
  691                         break;
  692 
  693                 case T_ATM_PVC_ADDR:
  694                         err = EINVAL;
  695                         goto done;
  696                 }
  697                 break;
  698 
  699         case T_ATM_ABSENT:
  700         case T_ATM_ANY:
  701                 break;
  702 
  703         default:
  704                 err = EINVAL;
  705                 goto done;
  706         }
  707 
  708         /*
  709          * Get an attribute block and save listening attributes
  710          */
  711         cop->co_lattr = uma_zalloc(atm_attributes_zone, M_WAITOK | M_ZERO);
  712         if (cop->co_lattr == NULL) {
  713                 err = ENOMEM;
  714                 goto done;
  715         }
  716         *cop->co_lattr = *ap;
  717 
  718         /*
  719          * Now try to register the listening connection
  720          */
  721         s = splnet();
  722         if (atm_cm_match(cop->co_lattr, NULL) != NULL) {
  723                 /*
  724                  * Can't have matching listeners
  725                  */
  726                 err = EADDRINUSE;
  727                 goto donex;
  728         }
  729         cop->co_state = COS_LISTEN;
  730         LINK2TAIL(cop, Atm_connection, atm_listen_queue, co_next);
  731 
  732 donex:
  733         (void) splx(s);
  734 
  735 done:
  736         if (err) {
  737                 /*
  738                  * Undo any partial setup stuff
  739                  */
  740                 if (cop) {
  741                         if (cop->co_lattr)
  742                                 uma_zfree(atm_attributes_zone, cop->co_lattr);
  743                         uma_zfree(atm_connection_zone, cop);
  744                 }
  745         } else {
  746                 /*
  747                  * Finish connection setup
  748                  */
  749                 *copp = cop;
  750         }
  751         return (err);
  752 }
  753 
  754 
  755 /*
  756  * Add to LLC Connection
  757  * 
  758  * Called by an endpoint service to create a new Connection Manager API
  759  * instance to be associated with an LLC-multiplexed connection instance
  760  * which has been previously created.  The endpoint provided token will
  761  * be used in all further CM -> endpoint function calls, and the returned
  762  * connection block pointer must be used in all subsequent endpoint -> CM
  763  * function calls.
  764  *
  765  * If the return indicates that the connection setup has been immediately
  766  * successful, then the connection is ready for data transmission.
  767  *
  768  * If the return indicates that the connection setup is still in progress,
  769  * then the endpoint must wait for notification from the Connection Manager
  770  * indicating the final status of the call setup.  If the call setup completes
  771  * successfully, then a "call connected" notification will be sent to the
  772  * endpoint by the Connection Manager.  If the call setup fails, then the
  773  * endpoint will receive a "call cleared" notification.
  774  *
  775  * All connection instances must be freed with an atm_cm_release() call.
  776  *
  777  * Arguments:
  778  *      epp     pointer to endpoint definition structure
  779  *      token   endpoint's connection instance token
  780  *      llc     pointer to llc attributes for new connection
  781  *      ecop    pointer to existing connection block
  782  *      copp    pointer to location to return allocated connection block
  783  *
  784  * Returns:
  785  *      0       connection has been successfully established
  786  *      EINPROGRESS     connection establishment is in progress
  787  *      errno   addllc failed - reason indicated
  788  *
  789  */
  790 int
  791 atm_cm_addllc(epp, token, llc, ecop, copp)
  792         Atm_endpoint    *epp;
  793         void            *token;
  794         struct attr_llc *llc;
  795         Atm_connection  *ecop;
  796         Atm_connection  **copp;
  797 {
  798         Atm_connection  *cop, *cop2;
  799         Atm_connvc      *cvp;
  800         int             s, err;
  801 
  802         *copp = NULL;
  803 
  804         /*
  805          * Check out requested LLC attributes
  806          */
  807         if ((llc->tag != T_ATM_PRESENT) ||
  808             ((llc->v.flags & T_ATM_LLC_SHARING) == 0) ||
  809             (llc->v.llc_len < T_ATM_LLC_MIN_LEN) ||
  810             (llc->v.llc_len > T_ATM_LLC_MAX_LEN))
  811                 return (EINVAL);
  812 
  813         /*
  814          * Get a connection block
  815          * May be called from netisr - don't wait.
  816          */
  817         cop = uma_zalloc(atm_connection_zone, M_NOWAIT);
  818         if (cop == NULL)
  819                 return (ENOMEM);
  820 
  821         /*
  822          * Initialize connection info
  823          */
  824         cop->co_endpt = epp;
  825         cop->co_toku = token;
  826         cop->co_llc = *llc;
  827 
  828         s = splnet();
  829 
  830         /*
  831          * Ensure that supplied connection is really valid
  832          */
  833         cop2 = NULL;
  834         for (cvp = Q_HEAD(atm_connection_queue, Atm_connvc); cvp;
  835                         cvp = Q_NEXT(cvp, Atm_connvc, cvc_q)) {
  836                 for (cop2 = cvp->cvc_conn; cop2; cop2 = cop2->co_next) {
  837                         if (ecop == cop2)
  838                                 break;
  839                 }
  840                 if (cop2)
  841                         break;
  842         }
  843         if (cop2 == NULL) {
  844                 err = ENOENT;
  845                 goto done;
  846         }
  847 
  848         switch (ecop->co_state) {
  849 
  850         case COS_OUTCONN:
  851         case COS_INACCEPT:
  852                 err = EINPROGRESS;
  853                 break;
  854 
  855         case COS_ACTIVE:
  856                 err = 0;
  857                 break;
  858 
  859         default:
  860                 err = EINVAL;
  861                 goto done;
  862         }
  863 
  864         /*
  865          * Connection must be LLC multiplexed and shared
  866          */
  867         if ((ecop->co_mpx != ATM_ENC_LLC) ||
  868             ((ecop->co_llc.v.flags & T_ATM_LLC_SHARING) == 0)) {
  869                 err = EINVAL;
  870                 goto done;
  871         }
  872 
  873         /*
  874          * This new LLC header must be unique for this VCC
  875          */
  876         cop2 = ecop->co_mxh;
  877         while (cop2) {
  878                 int     i = MIN(llc->v.llc_len, cop2->co_llc.v.llc_len);
  879 
  880                 if (bcmp(llc->v.llc_info, cop2->co_llc.v.llc_info, i) == 0) {
  881                         err = EINVAL;
  882                         goto done;
  883                 }
  884 
  885                 cop2 = cop2->co_next;
  886         }
  887 
  888         /*
  889          * Everything seems to check out
  890          */
  891         cop->co_flags = ecop->co_flags;
  892         cop->co_state = ecop->co_state;
  893         cop->co_mpx = ecop->co_mpx;
  894         cop->co_connvc = ecop->co_connvc;
  895 
  896         LINK2TAIL(cop, Atm_connection, ecop->co_mxh, co_next);
  897         cop->co_mxh = ecop->co_mxh;
  898 
  899 done:
  900         (void) splx(s);
  901 
  902         if (err && err != EINPROGRESS) {
  903                 /*
  904                  * Undo any partial setup stuff
  905                  */
  906                 if (cop)
  907                         uma_zfree(atm_connection_zone, cop);
  908         } else {
  909                 /*
  910                  * Pass new connection back to caller
  911                  */
  912                 *copp = cop;
  913         }
  914         return (err);
  915 }
  916 
  917 
  918 /*
  919  * XXX
  920  * 
  921  * Arguments:
  922  *      cop     pointer to connection block
  923  *      id      identifier for party to be added
  924  *      addr    address of party to be added
  925  *
  926  * Returns:
  927  *      0       addparty successful
  928  *      errno   addparty failed - reason indicated
  929  *
  930  */
  931 int
  932 atm_cm_addparty(cop, id, addr)
  933         Atm_connection  *cop;
  934         int             id;
  935         struct t_atm_sap        *addr;
  936 {
  937         return (0);
  938 }
  939 
  940 
  941 /*
  942  * XXX
  943  * 
  944  * Arguments:
  945  *      cop     pointer to connection block
  946  *      id      identifier for party to be added
  947  *      cause   pointer to cause of drop
  948  *
  949  * Returns:
  950  *      0       dropparty successful
  951  *      errno   dropparty failed - reason indicated
  952  *
  953  */
  954 int
  955 atm_cm_dropparty(cop, id, cause)
  956         Atm_connection  *cop;
  957         int             id;
  958         struct t_atm_cause      *cause;
  959 {
  960         return (0);
  961 }
  962 
  963 
  964 /*
  965  * Release Connection Resources
  966  * 
  967  * Called by the endpoint service in order to terminate an ATM connection 
  968  * and to release all system resources for the connection.  This function
  969  * must be called for every allocated connection instance and must only 
  970  * be called by the connection's owner.
  971  *
  972  * Arguments:
  973  *      cop     pointer to connection block
  974  *      cause   pointer to cause of release
  975  *
  976  * Returns:
  977  *      0       release successful
  978  *      errno   release failed - reason indicated
  979  *
  980  */
  981 int
  982 atm_cm_release(cop, cause)
  983         Atm_connection  *cop;
  984         struct t_atm_cause      *cause;
  985 {
  986         Atm_connvc      *cvp;
  987         int             s;
  988 
  989         s = splnet();
  990 
  991         /*
  992          * First, a quick state validation check
  993          */
  994         switch (cop->co_state) {
  995 
  996         case COS_OUTCONN:
  997         case COS_LISTEN:
  998         case COS_INACCEPT:
  999         case COS_ACTIVE:
 1000         case COS_CLEAR:
 1001                 /*
 1002                  * Break link to user
 1003                  */
 1004                 cop->co_toku = NULL;
 1005                 break;
 1006 
 1007         case COS_INCONN:
 1008                 (void) splx(s);
 1009                 return (EFAULT);
 1010 
 1011         default:
 1012                 panic("atm_cm_release: bogus conn state");
 1013         }
 1014 
 1015         /*
 1016          * Check out the VCC state too
 1017          */
 1018         if ((cvp = cop->co_connvc) != NULL) {
 1019 
 1020                 switch (cvp->cvc_state) {
 1021 
 1022                 case CVCS_SETUP:
 1023                 case CVCS_INIT:
 1024                 case CVCS_ACCEPT:
 1025                 case CVCS_ACTIVE:
 1026                         break;
 1027 
 1028                 case CVCS_INCOMING:
 1029                         (void) splx(s);
 1030                         return (EFAULT);
 1031 
 1032                 case CVCS_CLEAR:
 1033                         (void) splx(s);
 1034                         return (EALREADY);
 1035 
 1036                 default:
 1037                         panic("atm_cm_release: bogus connvc state");
 1038                 }
 1039 
 1040                 /*
 1041                  * If we're the only connection, terminate the VCC
 1042                  */
 1043                 if ((cop->co_mxh == cop) && (cop->co_next == NULL)) {
 1044                         cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
 1045                         cvp->cvc_attr.cause.v = *cause;
 1046                         atm_cm_closevc(cvp);
 1047                 }
 1048         }
 1049 
 1050         /*
 1051          * Now get rid of the connection
 1052          */
 1053         atm_cm_closeconn(cop, cause);
 1054 
 1055         return (0);
 1056 }
 1057 
 1058 
 1059 /*
 1060  * Abort an ATM Connection VCC
 1061  * 
 1062  * This function allows any non-owner kernel entity to request an 
 1063  * immediate termination of an ATM VCC.  This will normally be called
 1064  * when encountering a catastrophic error condition that cannot be 
 1065  * resolved via the available stack protocols.  The connection manager 
 1066  * will schedule the connection's termination, including notifying the 
 1067  * connection owner of the termination.  
 1068  *
 1069  * This function should only be called by a stack entity instance.  After 
 1070  * calling the function, the caller should set a protocol state which just 
 1071  * waits for a <sap>_TERM stack command to be delivered.
 1072  *
 1073  * Arguments:
 1074  *      cvp     pointer to connection VCC block
 1075  *      cause   pointer to cause of abort
 1076  *
 1077  * Returns:
 1078  *      0       abort successful
 1079  *      errno   abort failed - reason indicated
 1080  *
 1081  */
 1082 int
 1083 atm_cm_abort(cvp, cause)
 1084         Atm_connvc      *cvp;
 1085         struct t_atm_cause      *cause;
 1086 {
 1087         ATM_DEBUG2("atm_cm_abort: cvp=%p cause=%d\n",
 1088                 cvp, cause->cause_value);
 1089 
 1090         /*
 1091          * Note that we're aborting
 1092          */
 1093         cvp->cvc_flags |= CVCF_ABORTING;
 1094 
 1095         switch (cvp->cvc_state) {
 1096 
 1097         case CVCS_INIT:
 1098                 /*
 1099                  * In-line code will handle this
 1100                  */
 1101                 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
 1102                 cvp->cvc_attr.cause.v = *cause;
 1103                 break;
 1104 
 1105         case CVCS_SETUP:
 1106         case CVCS_ACCEPT:
 1107         case CVCS_ACTIVE:
 1108                 /*
 1109                  * Schedule connection termination, since we want
 1110                  * to avoid any sequencing interactions
 1111                  */
 1112                 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
 1113                 cvp->cvc_attr.cause.v = *cause;
 1114                 CVC_TIMER(cvp, 0);
 1115                 break;
 1116 
 1117         case CVCS_REJECT:
 1118         case CVCS_RELEASE:
 1119         case CVCS_CLEAR:
 1120         case CVCS_TERM:
 1121                 /*
 1122                  * Ignore abort, as we're already terminating
 1123                  */
 1124                 break;
 1125 
 1126         default:
 1127                 log(LOG_ERR,
 1128                         "atm_cm_abort: invalid state: cvp=%p, state=%d\n",
 1129                         cvp, cvp->cvc_state);
 1130         }
 1131         return (0);
 1132 }
 1133 
 1134 
 1135 /*
 1136  * Incoming ATM Call Received
 1137  * 
 1138  * Called by a signalling manager to indicate that a new call request has
 1139  * been received.  This function will allocate and initialize the connection
 1140  * manager control blocks and queue this call request.  The call request 
 1141  * processing function, atm_cm_procinq(), will be scheduled to perform the
 1142  * call processing.
 1143  *
 1144  * Arguments:
 1145  *      vcp     pointer to incoming call's VCC control block
 1146  *      ap      pointer to incoming call's attributes
 1147  *
 1148  * Returns:
 1149  *      0       call queuing successful
 1150  *      errno   call queuing failed - reason indicated
 1151  *
 1152  */
 1153 int
 1154 atm_cm_incoming(vcp, ap)
 1155         struct vccb     *vcp;
 1156         Atm_attributes  *ap;
 1157 {
 1158         Atm_connvc      *cvp;
 1159         int             s, err;
 1160 
 1161 
 1162         /*
 1163          * Do some minimal attribute validation
 1164          */
 1165 
 1166         /*
 1167          * Must specify a network interface
 1168          */
 1169         if (ap->nif == NULL)
 1170                 return (EINVAL);
 1171 
 1172         /*
 1173          * AAL Attributes
 1174          */
 1175         if ((ap->aal.tag != T_ATM_PRESENT) ||
 1176             ((ap->aal.type != ATM_AAL5) &&
 1177              (ap->aal.type != ATM_AAL3_4)))
 1178                 return (EINVAL);
 1179 
 1180         /*
 1181          * Traffic Descriptor Attributes
 1182          */
 1183         if ((ap->traffic.tag != T_ATM_PRESENT) &&
 1184             (ap->traffic.tag != T_ATM_ABSENT))
 1185                 return (EINVAL);
 1186 
 1187         /*
 1188          * Broadband Bearer Attributes
 1189          */
 1190         if ((ap->bearer.tag != T_ATM_PRESENT) ||
 1191             ((ap->bearer.v.connection_configuration != T_ATM_1_TO_1) &&
 1192              (ap->bearer.v.connection_configuration != T_ATM_1_TO_MANY)))
 1193                 return (EINVAL);
 1194 
 1195         /*
 1196          * Broadband High Layer Attributes
 1197          */
 1198         if ((ap->bhli.tag != T_ATM_PRESENT) &&
 1199             (ap->bhli.tag != T_ATM_ABSENT))
 1200                 return (EINVAL);
 1201 
 1202         /*
 1203          * Broadband Low Layer Attributes
 1204          */
 1205         if ((ap->blli.tag_l2 != T_ATM_PRESENT) &&
 1206             (ap->blli.tag_l2 != T_ATM_ABSENT))
 1207                 return (EINVAL);
 1208         if ((ap->blli.tag_l3 != T_ATM_PRESENT) &&
 1209             (ap->blli.tag_l3 != T_ATM_ABSENT))
 1210                 return (EINVAL);
 1211 
 1212         /*
 1213          * Logical Link Control Attributes
 1214          */
 1215         if (ap->llc.tag == T_ATM_PRESENT)
 1216                 return (EINVAL);
 1217         ap->llc.tag = T_ATM_ANY;
 1218 
 1219         /*
 1220          * Called Party Attributes
 1221          */
 1222         if ((ap->called.tag != T_ATM_PRESENT) ||
 1223             (ap->called.addr.address_format == T_ATM_ABSENT))
 1224                 return (EINVAL);
 1225         if (ap->called.tag == T_ATM_ABSENT) {
 1226                 ap->called.addr.address_format = T_ATM_ABSENT;
 1227                 ap->called.addr.address_length = 0;
 1228                 ap->called.subaddr.address_format = T_ATM_ABSENT;
 1229                 ap->called.subaddr.address_length = 0;
 1230         }
 1231 
 1232         /*
 1233          * Calling Party Attributes
 1234          */
 1235         if ((ap->calling.tag != T_ATM_PRESENT) &&
 1236             (ap->calling.tag != T_ATM_ABSENT))
 1237                 return (EINVAL);
 1238         if (ap->calling.tag == T_ATM_ABSENT) {
 1239                 ap->calling.addr.address_format = T_ATM_ABSENT;
 1240                 ap->calling.addr.address_length = 0;
 1241                 ap->calling.subaddr.address_format = T_ATM_ABSENT;
 1242                 ap->calling.subaddr.address_length = 0;
 1243         }
 1244 
 1245         /*
 1246          * Quality of Service Attributes
 1247          */
 1248         if (ap->qos.tag != T_ATM_PRESENT)
 1249                 return (EINVAL);
 1250 
 1251         /*
 1252          * Transit Network Attributes
 1253          */
 1254         if ((ap->transit.tag != T_ATM_PRESENT) &&
 1255             (ap->transit.tag != T_ATM_ABSENT))
 1256                 return (EINVAL);
 1257 
 1258         /*
 1259          * Cause Attributes
 1260          */
 1261         if ((ap->cause.tag != T_ATM_PRESENT) &&
 1262             (ap->cause.tag != T_ATM_ABSENT))
 1263                 return (EINVAL);
 1264 
 1265         /*
 1266          * Get a connection VCC block
 1267          * May be called from netisr - don't wait.
 1268          */
 1269         cvp = uma_zalloc(atm_connvc_zone, M_NOWAIT);
 1270         if (cvp == NULL) {
 1271                 err = ENOMEM;
 1272                 goto fail;
 1273         }
 1274 
 1275         /*
 1276          * Initialize the control block
 1277          */
 1278         cvp->cvc_vcc = vcp;
 1279         cvp->cvc_sigmgr = vcp->vc_pif->pif_sigmgr;
 1280         cvp->cvc_attr = *ap;
 1281         cvp->cvc_state = CVCS_INCOMING;
 1282 
 1283         /*
 1284          * Control queue length
 1285          */
 1286         s = splnet();
 1287         if (atm_incoming_qlen >= ATM_CALLQ_MAX) {
 1288                 (void) splx(s);
 1289                 err = EBUSY;
 1290                 goto fail;
 1291         }
 1292 
 1293         /*
 1294          * Queue request and schedule call processing function
 1295          */
 1296         cvp->cvc_flags |= CVCF_INCOMQ;
 1297         ENQUEUE(cvp, Atm_connvc, cvc_q, atm_incoming_queue);
 1298         if (atm_incoming_qlen++ == 0) {
 1299                 timeout(atm_cm_procinq, (void *)0, 0);
 1300         }
 1301 
 1302         /*
 1303          * Link for signalling manager
 1304          */
 1305         vcp->vc_connvc = cvp;
 1306 
 1307         (void) splx(s);
 1308 
 1309         return (0);
 1310 
 1311 fail:
 1312         /*
 1313          * Free any resources
 1314          */
 1315         if (cvp)
 1316                 uma_zfree(atm_connvc_zone, cvp);
 1317         return (err);
 1318 }
 1319 
 1320 
 1321 /*
 1322  * VCC Connected Notification
 1323  * 
 1324  * This function is called by a signalling manager as notification that a
 1325  * VCC call setup has been successful.
 1326  *
 1327  * Arguments:
 1328  *      cvp     pointer to connection VCC block
 1329  *
 1330  * Returns:
 1331  *      none
 1332  *
 1333  */
 1334 void
 1335 atm_cm_connected(cvp)
 1336         Atm_connvc      *cvp;
 1337 {
 1338         Atm_connection  *cop, *cop2;
 1339         KBuffer         *m;
 1340         int             s, err;
 1341 
 1342         s = splnet();
 1343 
 1344         /*
 1345          * Validate connection vcc
 1346          */
 1347         switch (cvp->cvc_state) {
 1348 
 1349         case CVCS_SETUP:
 1350                 /*
 1351                  * Initialize the stack
 1352                  */
 1353                 cvp->cvc_state = CVCS_INIT;
 1354                 STACK_CALL(atm_stackcmds[cvp->cvc_attr.api].init,
 1355                                 cvp->cvc_lower, cvp->cvc_tokl,
 1356                                 cvp, cvp->cvc_attr.api_init, 0, err);
 1357                 if (err)
 1358                         panic("atm_cm_connected: init");
 1359 
 1360                 if (cvp->cvc_flags & CVCF_ABORTING) {
 1361                         /*
 1362                          * Someone on the stack bailed out...notify all of the
 1363                          * connections and schedule the VCC termination
 1364                          */
 1365                         cop = cvp->cvc_conn;
 1366                         while (cop) {
 1367                                 cop2 = cop->co_next;
 1368                                 atm_cm_closeconn(cop, &cvp->cvc_attr.cause.v);
 1369                                 cop = cop2;
 1370                         }
 1371                         atm_cm_closevc(cvp);
 1372                         (void) splx(s);
 1373                         return;
 1374                 }
 1375                 break;
 1376 
 1377         case CVCS_ACCEPT:
 1378                 /*
 1379                  * Stack already initialized
 1380                  */
 1381                 break;
 1382 
 1383         default:
 1384                 panic("atm_cm_connected: connvc state");
 1385         }
 1386 
 1387         /*
 1388          * VCC is ready for action
 1389          */
 1390         cvp->cvc_state = CVCS_ACTIVE;
 1391 
 1392         /*
 1393          * Notify all connections that the call has completed
 1394          */
 1395         cop = cvp->cvc_conn;
 1396         while (cop) {
 1397                 cop2 = cop->co_next;
 1398 
 1399                 switch (cop->co_state) {
 1400 
 1401                 case COS_OUTCONN:
 1402                 case COS_INACCEPT:
 1403                         cop->co_state = COS_ACTIVE;
 1404                         (*cop->co_endpt->ep_connected)(cop->co_toku);
 1405                         break;
 1406 
 1407                 case COS_ACTIVE:
 1408                         /*
 1409                          * May get here if an ep_connected() call (from
 1410                          * above) results in an atm_cm_addllc() call for 
 1411                          * the just connected connection.
 1412                          */
 1413                         break;
 1414 
 1415                 default:
 1416                         panic("atm_cm_connected: connection state");
 1417                 }
 1418 
 1419                 cop = cop2;
 1420         }
 1421 
 1422         (void) splx(s);
 1423 
 1424         /*
 1425          * Input any queued packets
 1426          */
 1427         while ((m = cvp->cvc_rcvq) != NULL) {
 1428                 cvp->cvc_rcvq = KB_QNEXT(m);
 1429                 cvp->cvc_rcvqlen--;
 1430                 KB_QNEXT(m) = NULL;
 1431 
 1432                 /*
 1433                  * Currently only supported for CPCS API
 1434                  */
 1435                 atm_cm_cpcs_upper(CPCS_UNITDATA_SIG, cvp, (intptr_t)m, 0);
 1436         }
 1437 
 1438         return;
 1439 }
 1440 
 1441 
 1442 /*
 1443  * VCC Cleared Notification
 1444  * 
 1445  * This function is called by a signalling manager as notification that a
 1446  * VCC call has been cleared.  The cause information describing the reason
 1447  * for the call clearing will be contained in the connection VCC attributes.
 1448  *
 1449  * Arguments:
 1450  *      cvp     pointer to connection VCC block
 1451  *
 1452  * Returns:
 1453  *      none
 1454  *
 1455  */
 1456 void
 1457 atm_cm_cleared(cvp)
 1458         Atm_connvc      *cvp;
 1459 {
 1460         Atm_connection  *cop, *cop2;
 1461         int             s;
 1462 
 1463         KASSERT((cvp->cvc_state != CVCS_FREE) && (cvp->cvc_state < CVCS_CLEAR),
 1464             ("atm_cm_cleared: state sanity check failed"));
 1465 
 1466         cvp->cvc_state = CVCS_CLEAR;
 1467         s = splnet();
 1468 
 1469         /*
 1470          * Terminate all connections
 1471          */
 1472         cop = cvp->cvc_conn;
 1473         while (cop) {
 1474                 cop2 = cop->co_next;
 1475                 atm_cm_closeconn(cop, &cvp->cvc_attr.cause.v);
 1476                 cop = cop2;
 1477         }
 1478 
 1479         /*
 1480          * Clean up connection VCC
 1481          */
 1482         atm_cm_closevc(cvp);
 1483 
 1484         (void) splx(s);
 1485 
 1486         return;
 1487 }
 1488 
 1489 
 1490 /*
 1491  * Process Incoming Call Queue
 1492  * 
 1493  * This function is scheduled by atm_cm_incoming() in order to process
 1494  * all the entries on the incoming call queue.
 1495  *
 1496  * Arguments:
 1497  *      arg     argument passed on timeout() call
 1498  *
 1499  * Returns:
 1500  *      none
 1501  *
 1502  */
 1503 static KTimeout_ret
 1504 atm_cm_procinq(arg)
 1505         void    *arg;
 1506 {
 1507         Atm_connvc      *cvp;
 1508         int             cnt = 0, s;
 1509 
 1510         /*
 1511          * Only process incoming calls up to our quota
 1512          */
 1513         while (cnt++ < ATM_CALLQ_MAX) {
 1514 
 1515                 s = splnet();
 1516 
 1517                 /*
 1518                  * Get next awaiting call
 1519                  */
 1520                 cvp = Q_HEAD(atm_incoming_queue, Atm_connvc);
 1521                 if (cvp == NULL) {
 1522                         (void) splx(s);
 1523                         break;
 1524                 }
 1525                 DEQUEUE(cvp, Atm_connvc, cvc_q, atm_incoming_queue);
 1526                 atm_incoming_qlen--;
 1527                 cvp->cvc_flags &= ~CVCF_INCOMQ;
 1528 
 1529                 /*
 1530                  * Handle the call
 1531                  */
 1532                 atm_cm_incall(cvp);
 1533 
 1534                 (void) splx(s);
 1535         }
 1536 
 1537         /*
 1538          * If we've expended our quota, reschedule ourselves
 1539          */
 1540         if (cnt >= ATM_CALLQ_MAX)
 1541                 timeout(atm_cm_procinq, (void *)0, 0);
 1542 }
 1543 
 1544 
 1545 /*
 1546  * Process Incoming Call
 1547  * 
 1548  * This function will search through the listening queue and try to find
 1549  * matching endpoint(s) for the incoming call.  If we find any, we will
 1550  * notify the endpoint service(s) of the incoming call and will then
 1551  * notify the signalling manager to progress the call to an active status.
 1552  * 
 1553  * If there are no listeners for the call, the signalling manager will be
 1554  * notified of a call rejection.
 1555  *
 1556  * Called at splnet.
 1557  *
 1558  * Arguments:
 1559  *      cvp     pointer to connection VCC for incoming call
 1560  *
 1561  * Returns:
 1562  *      none
 1563  *
 1564  */
 1565 static void
 1566 atm_cm_incall(cvp)
 1567         Atm_connvc      *cvp;
 1568 {
 1569         Atm_connection  *cop, *lcop, *hcop;
 1570         Atm_attributes  attr;
 1571         int             err;
 1572 
 1573         hcop = NULL;
 1574         lcop = NULL;
 1575         cop = NULL;
 1576         attr = cvp->cvc_attr;
 1577 
 1578         /*
 1579          * Look for matching listeners
 1580          */
 1581         while ((lcop = atm_cm_match(&attr, lcop)) != NULL) {
 1582 
 1583                 if (cop == NULL) {
 1584                         /*
 1585                          * Need a new connection block
 1586                          * May be called from timeout - dont wait.
 1587                          */
 1588                         cop = uma_zalloc(atm_connection_zone, M_NOWAIT);
 1589                         if (cop == NULL) {
 1590                                 cvp->cvc_attr.cause = atm_cause_tmpl;
 1591                                 cvp->cvc_attr.cause.v.cause_value =
 1592                                                 T_ATM_CAUSE_TEMPORARY_FAILURE;
 1593                                 goto fail;
 1594                         }
 1595                 }
 1596 
 1597                 /*
 1598                  * Initialize connection from listener and incoming call
 1599                  */
 1600                 cop->co_mxh = NULL;
 1601                 cop->co_state = COS_INCONN;
 1602                 cop->co_mpx = lcop->co_mpx;
 1603                 cop->co_endpt = lcop->co_endpt;
 1604                 cop->co_llc = lcop->co_llc;
 1605 
 1606                 switch (attr.bearer.v.connection_configuration) {
 1607 
 1608                 case T_ATM_1_TO_1:
 1609                         cop->co_flags |= COF_P2P;
 1610                         break;
 1611 
 1612                 case T_ATM_1_TO_MANY:
 1613                         /* Not supported */
 1614                         cop->co_flags |= COF_P2MP;
 1615                         cvp->cvc_attr.cause = atm_cause_tmpl;
 1616                         cvp->cvc_attr.cause.v.cause_value =
 1617                                 T_ATM_CAUSE_BEARER_CAPABILITY_NOT_IMPLEMENTED;
 1618                         goto fail;
 1619                 }
 1620 
 1621                 /*
 1622                  * Notify endpoint of incoming call
 1623                  */
 1624                 err = (*cop->co_endpt->ep_incoming)
 1625                         (lcop->co_toku, cop, &cvp->cvc_attr, &cop->co_toku);
 1626 
 1627                 if (err == 0) {
 1628 
 1629                         /*
 1630                          * Endpoint has accepted the call
 1631                          *
 1632                          * Setup call attributes
 1633                          */
 1634                         if (hcop == NULL) {
 1635                                 cvp->cvc_attr.api = lcop->co_lattr->api;
 1636                                 cvp->cvc_attr.api_init =
 1637                                         lcop->co_lattr->api_init;
 1638                                 cvp->cvc_attr.llc = lcop->co_lattr->llc;
 1639                         }
 1640                         cvp->cvc_attr.headin = MAX(cvp->cvc_attr.headin,
 1641                                 lcop->co_lattr->headin);
 1642 
 1643                         /*
 1644                          * Setup connection info and queueing
 1645                          */
 1646                         cop->co_state = COS_INACCEPT;
 1647                         cop->co_connvc = cvp;
 1648                         LINK2TAIL(cop, Atm_connection, hcop, co_next);
 1649                         cop->co_mxh = hcop;
 1650 
 1651                         /*
 1652                          * Need a new connection block next time around
 1653                          */
 1654                         cop = NULL;
 1655 
 1656                 } else {
 1657                         /*
 1658                          * Endpoint refuses call
 1659                          */
 1660                         goto fail;
 1661                 }
 1662         }
 1663 
 1664         /*
 1665          * We're done looking for listeners
 1666          */
 1667         if (hcop) {
 1668                 /*
 1669                  * Someone actually wants the call, so notify
 1670                  * the signalling manager to continue
 1671                  */
 1672                 cvp->cvc_flags |= CVCF_CONNQ;
 1673                 ENQUEUE(cvp, Atm_connvc, cvc_q, atm_connection_queue);
 1674                 if (atm_cm_accept(cvp, hcop))
 1675                         goto fail;
 1676 
 1677         } else {
 1678                 /*
 1679                  * Nobody around to take the call
 1680                  */
 1681                 cvp->cvc_attr.cause = atm_cause_tmpl;
 1682                 cvp->cvc_attr.cause.v.cause_value =
 1683                                 T_ATM_CAUSE_INCOMPATIBLE_DESTINATION;
 1684                 goto fail;
 1685         }
 1686 
 1687         /*
 1688          * Clean up loose ends
 1689          */
 1690         if (cop)
 1691                 uma_zfree(atm_connection_zone, cop);
 1692 
 1693         /*
 1694          * Call has been accepted
 1695          */
 1696         return;
 1697 
 1698 fail:
 1699         /*
 1700          * Call failed - notify any endpoints of the call failure
 1701          */
 1702 
 1703         /*
 1704          * Clean up loose ends
 1705          */
 1706         if (cop)
 1707                 uma_zfree(atm_connection_zone, cop);
 1708 
 1709         if (cvp->cvc_attr.cause.tag != T_ATM_PRESENT) {
 1710                 cvp->cvc_attr.cause = atm_cause_tmpl;
 1711                 cvp->cvc_attr.cause.v.cause_value =
 1712                                 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
 1713         }
 1714         cop = hcop;
 1715         while (cop) {
 1716                 Atm_connection  *cop2 = cop->co_next;
 1717                 atm_cm_closeconn(cop, &cvp->cvc_attr.cause.v);
 1718                 cop = cop2;
 1719         }
 1720 
 1721         /*
 1722          * Tell the signalling manager to reject the call
 1723          */
 1724         atm_cm_closevc(cvp);
 1725 
 1726         return;
 1727 }
 1728 
 1729 
 1730 /*
 1731  * Accept an Incoming ATM Call
 1732  * 
 1733  * Some endpoint service(s) wants to accept an incoming call, so the
 1734  * signalling manager will be notified to attempt to progress the call
 1735  * to an active status.
 1736  *
 1737  * If the signalling manager indicates that connection activation has 
 1738  * been immediately successful, then all of the endpoints will be notified
 1739  * that the connection is ready for data transmission.
 1740  * 
 1741  * If the return indicates that connection activation is still in progress,
 1742  * then the endpoints must wait for notification from the Connection Manager
 1743  * indicating the final status of the call setup.  If the call setup completes
 1744  * successfully, then a "call connected" notification will be sent to the
 1745  * endpoints by the Connection Manager.  If the call setup fails, then the
 1746  * endpoints will receive a "call cleared" notification.
 1747  *
 1748  * Called at splnet.
 1749  *
 1750  * Arguments:
 1751  *      cvp     pointer to connection VCC for incoming call
 1752  *      cop     pointer to head of accepted connections
 1753  *
 1754  * Returns:
 1755  *      0       connection has been successfully activated
 1756  *      errno   accept failed - reason indicated
 1757  *
 1758  */
 1759 static int
 1760 atm_cm_accept(cvp, cop)
 1761         Atm_connvc      *cvp;
 1762         Atm_connection  *cop;
 1763 {
 1764         struct stack_list       sl;
 1765         void            (*upf)(int, void *, intptr_t, intptr_t);
 1766         int             sli, err, err2;
 1767 
 1768 
 1769         /*
 1770          * Link vcc to connections
 1771          */
 1772         cvp->cvc_conn = cop;
 1773 
 1774         /*
 1775          * Initialize stack list index
 1776          */
 1777         sli = 0;
 1778 
 1779         /*
 1780          * Check out Data API
 1781          */
 1782         switch (cvp->cvc_attr.api) {
 1783 
 1784         case CMAPI_CPCS:
 1785                 upf = atm_cm_cpcs_upper;
 1786                 break;
 1787 
 1788         case CMAPI_SAAL:
 1789                 sl.sl_sap[sli++] = SAP_SSCF_UNI;
 1790                 sl.sl_sap[sli++] = SAP_SSCOP;
 1791                 upf = atm_cm_saal_upper;
 1792                 break;
 1793 
 1794         case CMAPI_SSCOP:
 1795                 sl.sl_sap[sli++] = SAP_SSCOP;
 1796                 upf = atm_cm_sscop_upper;
 1797                 break;
 1798 
 1799         default:
 1800                 upf = NULL;
 1801         }
 1802 
 1803         /*
 1804          * AAL Attributes
 1805          */
 1806         switch (cvp->cvc_attr.aal.type) {
 1807 
 1808         case ATM_AAL5:
 1809                 sl.sl_sap[sli++] = SAP_CPCS_AAL5;
 1810                 sl.sl_sap[sli++] = SAP_SAR_AAL5;
 1811                 sl.sl_sap[sli++] = SAP_ATM;
 1812                 break;
 1813 
 1814         case ATM_AAL3_4:
 1815                 sl.sl_sap[sli++] = SAP_CPCS_AAL3_4;
 1816                 sl.sl_sap[sli++] = SAP_SAR_AAL3_4;
 1817                 sl.sl_sap[sli++] = SAP_ATM;
 1818                 break;
 1819         }
 1820 
 1821         /*
 1822          * Terminate stack list 
 1823          */
 1824         sl.sl_sap[sli] = 0;
 1825 
 1826         /*
 1827          * Create a service stack
 1828          */
 1829         err = atm_create_stack(cvp, &sl, upf);
 1830         if (err) {
 1831                 goto done;
 1832         }
 1833 
 1834         /*
 1835          * Let the signalling manager finish the VCC activation
 1836          */
 1837         switch ((*cvp->cvc_sigmgr->sm_accept)(cvp->cvc_vcc, &err)) {
 1838 
 1839         case CALL_PROCEEDING:
 1840                 /*
 1841                  * Note that we're not finished yet
 1842                  */
 1843                 err = EINPROGRESS;
 1844                 /* FALLTHRU */
 1845 
 1846         case CALL_CONNECTED:
 1847                 /*
 1848                  * Initialize the stack now, even if the call isn't totally
 1849                  * active yet.  We want to avoid the delay between getting
 1850                  * the "call connected" event and actually notifying the 
 1851                  * adapter to accept cells on the new VCC - if the delay is 
 1852                  * too long, then we end up dropping the first pdus sent by 
 1853                  * the caller.
 1854                  */
 1855                 cvp->cvc_state = CVCS_INIT;
 1856                 STACK_CALL(atm_stackcmds[cvp->cvc_attr.api].init,
 1857                                 cvp->cvc_lower, cvp->cvc_tokl, cvp,
 1858                                 cvp->cvc_attr.api_init, 0, err2);
 1859                 if (err2)
 1860                         panic("atm_cm_accept: init");
 1861 
 1862                 if (cvp->cvc_flags & CVCF_ABORTING) {
 1863                         /*
 1864                          * Someone on the stack bailed out...schedule the 
 1865                          * VCC and stack termination
 1866                          */
 1867                         err = ECONNABORTED;
 1868                 } else {
 1869                         /*
 1870                          * Everything looks fine from here
 1871                          */
 1872                         if (err)
 1873                                 cvp->cvc_state = CVCS_ACCEPT;
 1874                         else
 1875                                 cvp->cvc_state = CVCS_ACTIVE;
 1876                 }
 1877                 break;
 1878 
 1879         case CALL_FAILED:
 1880                 /*
 1881                  * Terminate stack and clean up before we leave
 1882                  */
 1883                 cvp->cvc_state = CVCS_CLEAR;
 1884                 break;
 1885 
 1886         default:
 1887                 panic("atm_cm_accept: accept");
 1888         }
 1889 
 1890 done:
 1891         if (err == 0) {
 1892                 /*
 1893                  * Call has been connected, notify endpoints
 1894                  */
 1895                 while (cop) {
 1896                         Atm_connection  *cop2 = cop->co_next;
 1897 
 1898                         cop->co_state = COS_ACTIVE;
 1899                         (*cop->co_endpt->ep_connected)(cop->co_toku);
 1900                         cop = cop2;
 1901                 }
 1902 
 1903         } else if (err == EINPROGRESS) {
 1904                 /*
 1905                  * Call is still in progress, endpoint must wait
 1906                  */
 1907                 err = 0;
 1908 
 1909         } else {
 1910                 /*
 1911                  * Let caller know we failed
 1912                  */
 1913                 cvp->cvc_attr.cause = atm_cause_tmpl;
 1914                 cvp->cvc_attr.cause.v.cause_value =
 1915                                 T_ATM_CAUSE_UNSPECIFIED_RESOURCE_UNAVAILABLE;
 1916         }
 1917 
 1918         return (err);
 1919 }
 1920 
 1921 
 1922 /*
 1923  * Match Attributes on Listening Queue
 1924  * 
 1925  * This function will attempt to match the supplied connection attributes
 1926  * with one of the registered attributes in the listening queue.  The pcop
 1927  * argument may be supplied in order to allow multiple listeners to share 
 1928  * an incoming call (if supported by the listeners).
 1929  *
 1930  * Called at splnet.
 1931  *
 1932  * Arguments:
 1933  *      ap      pointer to attributes to be matched
 1934  *      pcop    pointer to the previously matched connection
 1935  *
 1936  * Returns:
 1937  *      addr    connection with which a match was found
 1938  *      0       no match found
 1939  *
 1940  */
 1941 Atm_connection *
 1942 atm_cm_match(ap, pcop)
 1943         Atm_attributes  *ap;
 1944         Atm_connection  *pcop;
 1945 {
 1946         Atm_connection  *cop;
 1947         Atm_attributes  *lap;
 1948 
 1949 
 1950         /*
 1951          * If we've already matched a listener...
 1952          */
 1953         if (pcop) {
 1954                 /*
 1955                  * Make sure already matched listener supports sharing
 1956                  */
 1957                 if ((pcop->co_mpx != ATM_ENC_LLC) ||
 1958                     ((pcop->co_llc.v.flags & T_ATM_LLC_SHARING) == 0))
 1959                         return (NULL);
 1960 
 1961                 /*
 1962                  * Position ourselves after the matched entry
 1963                  */
 1964                 for (cop = atm_listen_queue; cop; cop = cop->co_next) {
 1965                         if (cop == pcop) {
 1966                                 cop = pcop->co_next;
 1967                                 break;
 1968                         }
 1969                 }
 1970         } else {
 1971                 /*
 1972                  * Start search at top of listening queue
 1973                  */
 1974                 cop = atm_listen_queue;
 1975         }
 1976 
 1977         /*
 1978          * Search through listening queue
 1979          */
 1980         for (; cop; cop = cop->co_next) {
 1981 
 1982                 lap = cop->co_lattr;
 1983 
 1984                 /*
 1985                  * If we're trying to share, check that this entry allows it
 1986                  */
 1987                 if (pcop) {
 1988                         if ((cop->co_mpx != ATM_ENC_LLC) ||
 1989                             ((cop->co_llc.v.flags & T_ATM_LLC_SHARING) == 0))
 1990                                 continue;
 1991                 }
 1992 
 1993                 /*
 1994                  * ALL "matchable" attributes must match
 1995                  */
 1996 
 1997                 /*
 1998                  * BHLI
 1999                  */
 2000                 if (lap->bhli.tag == T_ATM_ABSENT) {
 2001                         if (ap->bhli.tag == T_ATM_PRESENT)
 2002                                 continue;
 2003                 } else if (lap->bhli.tag == T_ATM_PRESENT) {
 2004                         if (ap->bhli.tag == T_ATM_ABSENT)
 2005                                 continue;
 2006                         if (ap->bhli.tag == T_ATM_PRESENT)
 2007                                 if (bcmp(&lap->bhli.v, &ap->bhli.v, 
 2008                                                 sizeof(struct t_atm_bhli)))
 2009                                         continue;
 2010                 }
 2011 
 2012                 /*
 2013                  * BLLI Layer 2
 2014                  */
 2015                 if (lap->blli.tag_l2 == T_ATM_ABSENT) {
 2016                         if (ap->blli.tag_l2 == T_ATM_PRESENT)
 2017                                 continue;
 2018                 } else if (lap->blli.tag_l2 == T_ATM_PRESENT) {
 2019                         if (ap->blli.tag_l2 == T_ATM_ABSENT)
 2020                                 continue;
 2021                         if (ap->blli.tag_l2 == T_ATM_PRESENT) {
 2022                                 if (bcmp(&lap->blli.v.layer_2_protocol.ID,
 2023                                            &ap->blli.v.layer_2_protocol.ID, 
 2024                                            sizeof(
 2025                                               ap->blli.v.layer_2_protocol.ID)))
 2026                                         continue;
 2027                         }
 2028                 }
 2029 
 2030                 /*
 2031                  * BLLI Layer 3
 2032                  */
 2033                 if (lap->blli.tag_l3 == T_ATM_ABSENT) {
 2034                         if (ap->blli.tag_l3 == T_ATM_PRESENT)
 2035                                 continue;
 2036                 } else if (lap->blli.tag_l3 == T_ATM_PRESENT) {
 2037                         if (ap->blli.tag_l3 == T_ATM_ABSENT)
 2038                                 continue;
 2039                         if (ap->blli.tag_l3 == T_ATM_PRESENT) {
 2040                                 if (bcmp(&lap->blli.v.layer_3_protocol.ID,
 2041                                            &ap->blli.v.layer_3_protocol.ID, 
 2042                                            sizeof(
 2043                                               ap->blli.v.layer_3_protocol.ID)))
 2044                                         continue;
 2045                         }
 2046                 }
 2047 
 2048                 /*
 2049                  * LLC
 2050                  */
 2051                 if (lap->llc.tag == T_ATM_ABSENT) {
 2052                         if (ap->llc.tag == T_ATM_PRESENT)
 2053                                 continue;
 2054                 } else if (lap->llc.tag == T_ATM_PRESENT) {
 2055                         if (ap->llc.tag == T_ATM_ABSENT)
 2056                                 continue;
 2057                         if (ap->llc.tag == T_ATM_PRESENT) {
 2058                                 int     i = MIN(lap->llc.v.llc_len,
 2059                                                         ap->llc.v.llc_len);
 2060 
 2061                                 if (bcmp(lap->llc.v.llc_info,
 2062                                                         ap->llc.v.llc_info, i))
 2063                                         continue;
 2064                         }
 2065                 }
 2066 
 2067                 /*
 2068                  * AAL
 2069                  */
 2070                 if (lap->aal.tag == T_ATM_ABSENT) {
 2071                         if (ap->aal.tag == T_ATM_PRESENT)
 2072                                 continue;
 2073                 } else if (lap->aal.tag == T_ATM_PRESENT) {
 2074                         if (ap->aal.tag == T_ATM_ABSENT)
 2075                                 continue;
 2076                         if (ap->aal.tag == T_ATM_PRESENT) {
 2077                                 if (lap->aal.type != ap->aal.type)
 2078                                         continue;
 2079                                 if (lap->aal.type == ATM_AAL5) {
 2080                                         if (lap->aal.v.aal5.SSCS_type !=
 2081                                                     ap->aal.v.aal5.SSCS_type)
 2082                                                 continue;
 2083                                 } else {
 2084                                         if (lap->aal.v.aal4.SSCS_type !=
 2085                                                     ap->aal.v.aal4.SSCS_type)
 2086                                                 continue;
 2087                                 }
 2088                         }
 2089                 }
 2090 
 2091                 /*
 2092                  * Called Party
 2093                  */
 2094                 if (lap->called.tag == T_ATM_ABSENT) {
 2095                         if (ap->called.tag == T_ATM_PRESENT)
 2096                                 continue;
 2097                 } else if (lap->called.tag == T_ATM_PRESENT) {
 2098                         if (ap->called.tag == T_ATM_ABSENT)
 2099                                 continue;
 2100                         if (ap->called.tag == T_ATM_PRESENT) {
 2101                                 if ((!ATM_ADDR_EQUAL(&lap->called.addr,
 2102                                                 &ap->called.addr)) ||
 2103                                     (!ATM_ADDR_EQUAL(&lap->called.subaddr,
 2104                                                 &ap->called.subaddr)))
 2105                                         continue;
 2106                         }
 2107                 }
 2108 
 2109                 /*
 2110                  * Found a full match - return it
 2111                  */
 2112                 break;
 2113         }
 2114 
 2115         return (cop);
 2116 }
 2117 
 2118 
 2119 /*
 2120  * Find Shareable LLC VCC
 2121  * 
 2122  * Given an endpoint-supplied connection attribute using LLC multiplexing,
 2123  * this function will attempt to locate an existing connection which meets
 2124  * the requirements of the supplied attributes.
 2125  *
 2126  * Called at splnet.
 2127  *
 2128  * Arguments:
 2129  *      ap      pointer to requested attributes
 2130  *
 2131  * Returns:
 2132  *      addr    shareable LLC connection VCC
 2133  *      0       no shareable VCC available
 2134  *
 2135  */
 2136 static Atm_connvc *
 2137 atm_cm_share_llc(ap)
 2138         Atm_attributes  *ap;
 2139 {
 2140         Atm_connection  *cop;
 2141         Atm_connvc      *cvp;
 2142 
 2143         /*
 2144          * Is requestor willing to share?
 2145          */
 2146         if ((ap->llc.v.flags & T_ATM_LLC_SHARING) == 0)
 2147                 return (NULL);
 2148 
 2149         /*
 2150          * Try to find a shareable connection
 2151          */
 2152         for (cvp = Q_HEAD(atm_connection_queue, Atm_connvc); cvp;
 2153                         cvp = Q_NEXT(cvp, Atm_connvc, cvc_q)) {
 2154 
 2155                 /*
 2156                  * Dont use terminating connections
 2157                  */
 2158                 switch (cvp->cvc_state) {
 2159 
 2160                 case CVCS_SETUP:
 2161                 case CVCS_ACCEPT:
 2162                 case CVCS_ACTIVE:
 2163                         break;
 2164 
 2165                 default:
 2166                         continue;
 2167                 }
 2168 
 2169                 /*
 2170                  * Is connection LLC and shareable?
 2171                  */
 2172                 if ((cvp->cvc_attr.llc.tag != T_ATM_PRESENT) ||
 2173                     ((cvp->cvc_attr.llc.v.flags & T_ATM_LLC_SHARING) == 0))
 2174                         continue;
 2175 
 2176                 /*
 2177                  * Match requested attributes with existing connection
 2178                  */
 2179                 if (ap->nif != cvp->cvc_attr.nif)
 2180                         continue;
 2181 
 2182                 if ((ap->api != cvp->cvc_attr.api) ||
 2183                     (ap->api_init != cvp->cvc_attr.api_init))
 2184                         continue;
 2185 
 2186                 /*
 2187                  * Remote Party
 2188                  */
 2189                 if (cvp->cvc_flags & CVCF_CALLER) {
 2190                         if ((!ATM_ADDR_EQUAL(&ap->called.addr,
 2191                                         &cvp->cvc_attr.called.addr)) ||
 2192                             (!ATM_ADDR_EQUAL(&ap->called.subaddr,
 2193                                         &cvp->cvc_attr.called.subaddr)))
 2194                                 continue;
 2195                 } else {
 2196                         if (cvp->cvc_attr.calling.tag != T_ATM_PRESENT)
 2197                                 continue;
 2198                         if ((!ATM_ADDR_EQUAL(&ap->called.addr,
 2199                                         &cvp->cvc_attr.calling.addr)) ||
 2200                             (!ATM_ADDR_EQUAL(&ap->called.subaddr,
 2201                                         &cvp->cvc_attr.calling.subaddr)))
 2202                                 continue;
 2203                 }
 2204 
 2205                 /*
 2206                  * AAL
 2207                  */
 2208                 if (ap->aal.type == ATM_AAL5) {
 2209                         struct t_atm_aal5       *ap5, *cv5;
 2210 
 2211                         ap5 = &ap->aal.v.aal5;
 2212                         cv5 = &cvp->cvc_attr.aal.v.aal5;
 2213 
 2214                         if ((cvp->cvc_attr.aal.type != ATM_AAL5) ||
 2215                             (ap5->SSCS_type != cv5->SSCS_type))
 2216                                 continue;
 2217 
 2218                         if (cvp->cvc_flags & CVCF_CALLER) {
 2219                                 if (ap5->forward_max_SDU_size >
 2220                                                 cv5->forward_max_SDU_size)
 2221                                         continue;
 2222                         } else {
 2223                                 if (ap5->forward_max_SDU_size >
 2224                                                 cv5->backward_max_SDU_size)
 2225                                         continue;
 2226                         }
 2227                 } else {
 2228                         struct t_atm_aal4       *ap4, *cv4;
 2229 
 2230                         ap4 = &ap->aal.v.aal4;
 2231                         cv4 = &cvp->cvc_attr.aal.v.aal4;
 2232 
 2233                         if ((cvp->cvc_attr.aal.type != ATM_AAL3_4) ||
 2234                             (ap4->SSCS_type != cv4->SSCS_type))
 2235                                 continue;
 2236 
 2237                         if (cvp->cvc_flags & CVCF_CALLER) {
 2238                                 if (ap4->forward_max_SDU_size >
 2239                                                 cv4->forward_max_SDU_size)
 2240                                         continue;
 2241                         } else {
 2242                                 if (ap4->forward_max_SDU_size >
 2243                                                 cv4->backward_max_SDU_size)
 2244                                         continue;
 2245                         }
 2246                 }
 2247 
 2248                 /*
 2249                  * Traffic Descriptor
 2250                  */
 2251                 if ((ap->traffic.tag != T_ATM_PRESENT) ||
 2252                     (cvp->cvc_attr.traffic.tag != T_ATM_PRESENT) ||
 2253                     (ap->traffic.v.best_effort != T_YES) ||
 2254                     (cvp->cvc_attr.traffic.v.best_effort != T_YES))
 2255                         continue;
 2256 
 2257                 /*
 2258                  * Broadband Bearer
 2259                  */
 2260                 if (ap->bearer.v.connection_configuration !=
 2261                                 cvp->cvc_attr.bearer.v.connection_configuration)
 2262                         continue;
 2263 
 2264                 /*
 2265                  * QOS
 2266                  */
 2267                 if (cvp->cvc_flags & CVCF_CALLER) {
 2268                         if ((ap->qos.v.forward.qos_class !=
 2269                                 cvp->cvc_attr.qos.v.forward.qos_class) ||
 2270                             (ap->qos.v.backward.qos_class !=
 2271                                 cvp->cvc_attr.qos.v.backward.qos_class))
 2272                                 continue;
 2273                 } else {
 2274                         if ((ap->qos.v.forward.qos_class !=
 2275                                 cvp->cvc_attr.qos.v.backward.qos_class) ||
 2276                             (ap->qos.v.backward.qos_class !=
 2277                                 cvp->cvc_attr.qos.v.forward.qos_class))
 2278                                 continue;
 2279                 }
 2280 
 2281                 /*
 2282                  * The new LLC header must also be unique for this VCC
 2283                  */
 2284                 for (cop = cvp->cvc_conn; cop; cop = cop->co_next) {
 2285                         int     i = MIN(ap->llc.v.llc_len,
 2286                                         cop->co_llc.v.llc_len);
 2287 
 2288                         if (bcmp(ap->llc.v.llc_info, 
 2289                                    cop->co_llc.v.llc_info, i) == 0)
 2290                                 break;
 2291                 }
 2292 
 2293                 /*
 2294                  * If no header overlaps, then we're done
 2295                  */
 2296                 if (cop == NULL)
 2297                         break;
 2298         }
 2299 
 2300         return (cvp);
 2301 }
 2302 
 2303 
 2304 /*
 2305  * Close Connection
 2306  * 
 2307  * This function will terminate a connection, including notifying the
 2308  * user, if necessary, and freeing up control block memory.  The caller
 2309  * is responsible for managing the connection VCC.
 2310  *
 2311  * Called at splnet.
 2312  *
 2313  * Arguments:
 2314  *      cop     pointer to connection block
 2315  *      cause   pointer to cause of close
 2316  *
 2317  * Returns:
 2318  *      none
 2319  *
 2320  */
 2321 static void
 2322 atm_cm_closeconn(cop, cause)
 2323         Atm_connection  *cop;
 2324         struct t_atm_cause      *cause;
 2325 {
 2326 
 2327         /*
 2328          * Decide whether user needs notification
 2329          */
 2330         switch (cop->co_state) {
 2331 
 2332         case COS_OUTCONN:
 2333         case COS_LISTEN:
 2334         case COS_INCONN:
 2335         case COS_INACCEPT:
 2336         case COS_ACTIVE:
 2337                 /*
 2338                  * Yup, let 'em know connection is gone
 2339                  */
 2340                 if (cop->co_toku)
 2341                         (*cop->co_endpt->ep_cleared)(cop->co_toku, cause);
 2342                 break;
 2343 
 2344         case COS_CLEAR:
 2345                 /*
 2346                  * Nope,they should know already
 2347                  */
 2348                 break;
 2349 
 2350         default:
 2351                 panic("atm_cm_closeconn: bogus state");
 2352         }
 2353 
 2354         /*
 2355          * Unlink connection from its queues
 2356          */
 2357         switch (cop->co_state) {
 2358 
 2359         case COS_LISTEN:
 2360                 uma_zfree(atm_attributes_zone, cop->co_lattr);
 2361                 UNLINK(cop, Atm_connection, atm_listen_queue, co_next);
 2362                 break;
 2363 
 2364         default:
 2365                 /*
 2366                  * Remove connection from multiplexor queue
 2367                  */
 2368                 if (cop->co_mxh != cop) {
 2369                         /*
 2370                          * Connection is down the chain, just unlink it
 2371                          */
 2372                         UNLINK(cop, Atm_connection, cop->co_mxh, co_next);
 2373 
 2374                 } else if (cop->co_next != NULL) {
 2375                         /*
 2376                          * Connection is at the head of a non-singleton chain,
 2377                          * so unlink and reset the chain head
 2378                          */
 2379                         Atm_connection  *t, *nhd;
 2380 
 2381                         t = nhd = cop->co_next;
 2382                         while (t) {
 2383                                 t->co_mxh = nhd;
 2384                                 t = t->co_next;
 2385                         }
 2386                         if (nhd->co_connvc)
 2387                                 nhd->co_connvc->cvc_conn = nhd;
 2388                 }
 2389         }
 2390 
 2391         /*
 2392          * Free the connection block
 2393          */
 2394         cop->co_state = COS_FREE;
 2395         uma_zfree(atm_connection_zone, cop);
 2396         return;
 2397 }
 2398 
 2399 
 2400 /*
 2401  * Close Connection VCC
 2402  * 
 2403  * This function will terminate a connection VCC, including releasing the
 2404  * the call to the signalling manager, terminating the VCC protocol stack,
 2405  * and freeing up control block memory.
 2406  *
 2407  * Called at splnet.
 2408  *
 2409  * Arguments:
 2410  *      cvp     pointer to connection VCC block
 2411  *
 2412  * Returns:
 2413  *      none
 2414  *
 2415  */
 2416 static void
 2417 atm_cm_closevc(cvp)
 2418         Atm_connvc      *cvp;
 2419 {
 2420         int     err;
 2421 
 2422         /*
 2423          * Break links with the connection block
 2424          */
 2425         cvp->cvc_conn = NULL;
 2426 
 2427         /*
 2428          * Cancel any running timer
 2429          */
 2430         CVC_CANCEL(cvp);
 2431 
 2432         /*
 2433          * Free queued packets
 2434          */
 2435         while (cvp->cvc_rcvq) {
 2436                 KBuffer         *m;
 2437 
 2438                 m = cvp->cvc_rcvq;
 2439                 cvp->cvc_rcvq = KB_QNEXT(m);
 2440                 KB_QNEXT(m) = NULL;
 2441                 KB_FREEALL(m);
 2442         }
 2443 
 2444         /*
 2445          * Unlink from any queues
 2446          */
 2447         if (cvp->cvc_flags & CVCF_INCOMQ) {
 2448                 DEQUEUE(cvp, Atm_connvc, cvc_q, atm_incoming_queue);
 2449                 atm_incoming_qlen--;
 2450                 cvp->cvc_flags &=  ~CVCF_INCOMQ;
 2451 
 2452         } else if (cvp->cvc_flags & CVCF_CONNQ) {
 2453                 DEQUEUE(cvp, Atm_connvc, cvc_q, atm_connection_queue);
 2454                 cvp->cvc_flags &=  ~CVCF_CONNQ;
 2455         }
 2456 
 2457         /*
 2458          * Release the signalling call
 2459          */
 2460         switch (cvp->cvc_state) {
 2461 
 2462         case CVCS_SETUP:
 2463         case CVCS_INIT:
 2464         case CVCS_ACCEPT:
 2465         case CVCS_ACTIVE:
 2466         case CVCS_RELEASE:
 2467                 if (cvp->cvc_vcc) {
 2468                         cvp->cvc_state = CVCS_RELEASE;
 2469                         switch ((*cvp->cvc_sigmgr->sm_release)
 2470                                 (cvp->cvc_vcc, &err)) {
 2471 
 2472                         case CALL_CLEARED:
 2473                                 /*
 2474                                  * Looks good so far...
 2475                                  */
 2476                                 break;
 2477 
 2478                         case CALL_PROCEEDING:
 2479                                 /*
 2480                                  * We'll have to wait for the call to clear
 2481                                  */
 2482                                 return;
 2483 
 2484                         case CALL_FAILED:
 2485                                 /*
 2486                                  * If there's a memory shortage, retry later.
 2487                                  * Otherwise who knows what's going on....
 2488                                  */
 2489                                 if ((err == ENOMEM) || (err == ENOBUFS)) {
 2490                                         CVC_TIMER(cvp, 1 * ATM_HZ);
 2491                                         return;
 2492                                 }
 2493                                 log(LOG_ERR,
 2494                                         "atm_cm_closevc: release %d\n", err);
 2495                                 break;
 2496                         }
 2497                 }
 2498                 break;
 2499 
 2500         case CVCS_INCOMING:
 2501         case CVCS_REJECT:
 2502                 if (cvp->cvc_vcc) {
 2503                         cvp->cvc_state = CVCS_REJECT;
 2504                         switch ((*cvp->cvc_sigmgr->sm_reject)
 2505                                 (cvp->cvc_vcc, &err)) {
 2506 
 2507                         case CALL_CLEARED:
 2508                                 /*
 2509                                  * Looks good so far...
 2510                                  */
 2511                                 break;
 2512 
 2513                         case CALL_FAILED:
 2514                                 /*
 2515                                  * If there's a memory shortage, retry later.
 2516                                  * Otherwise who knows what's going on....
 2517                                  */
 2518                                 if ((err == ENOMEM) || (err == ENOBUFS)) {
 2519                                         CVC_TIMER(cvp, 1 * ATM_HZ);
 2520                                         return;
 2521                                 }
 2522                                 log(LOG_ERR,
 2523                                         "atm_cm_closevc: reject %d\n", err);
 2524                                 break;
 2525                         }
 2526                 }
 2527                 break;
 2528 
 2529         case CVCS_CLEAR:
 2530         case CVCS_TERM:
 2531                 /*
 2532                  * No need for anything here
 2533                  */
 2534                 break;
 2535 
 2536         default:
 2537                 panic("atm_cm_closevc: bogus state");
 2538         }
 2539 
 2540         /*
 2541          * Now terminate the stack
 2542          */
 2543         if (cvp->cvc_tokl) {
 2544                 cvp->cvc_state = CVCS_TERM;
 2545 
 2546                 /*
 2547                  * Wait until stack is unwound before terminating
 2548                  */
 2549                 if ((cvp->cvc_downcnt > 0) || (cvp->cvc_upcnt > 0)) {
 2550                         CVC_TIMER(cvp, 0);
 2551                         return;
 2552                 }
 2553 
 2554                 STACK_CALL(atm_stackcmds[cvp->cvc_attr.api].term,
 2555                         cvp->cvc_lower, cvp->cvc_tokl, cvp, 0, 0, err);
 2556 
 2557                 cvp->cvc_tokl = NULL;
 2558         }
 2559 
 2560         /*
 2561          * Let signalling manager finish up
 2562          */
 2563         cvp->cvc_state = CVCS_FREE;
 2564         if (cvp->cvc_vcc) {
 2565                 (void) (*cvp->cvc_sigmgr->sm_free)(cvp->cvc_vcc);
 2566         }
 2567 
 2568         /*
 2569          * Finally, free our own control blocks
 2570          */
 2571         uma_zfree(atm_connvc_zone, cvp);
 2572         return;
 2573 }
 2574 
 2575 
 2576 /*
 2577  * Process a Connection VCC timeout
 2578  * 
 2579  * Called when a previously scheduled cvc control block timer expires.  
 2580  * Processing will be based on the current cvc state.
 2581  *
 2582  * Called at splnet.
 2583  *
 2584  * Arguments:
 2585  *      tip     pointer to cvc timer control block
 2586  *
 2587  * Returns:
 2588  *      none
 2589  *
 2590  */
 2591 static void
 2592 atm_cm_timeout(tip)
 2593         struct atm_time *tip;
 2594 {
 2595         Atm_connection  *cop, *cop2;
 2596         Atm_connvc      *cvp;
 2597 
 2598         /*
 2599          * Back-off to cvc control block
 2600          */
 2601         cvp = (Atm_connvc *)
 2602                         ((caddr_t)tip - (int)(&((Atm_connvc *)0)->cvc_time));
 2603 
 2604         /*
 2605          * Process timeout based on protocol state
 2606          */
 2607         switch (cvp->cvc_state) {
 2608 
 2609         case CVCS_SETUP:
 2610         case CVCS_ACCEPT:
 2611         case CVCS_ACTIVE:
 2612                 /*
 2613                  * Handle VCC abort
 2614                  */
 2615                 if ((cvp->cvc_flags & CVCF_ABORTING) == 0)
 2616                         goto logerr;
 2617 
 2618                 /*
 2619                  * Terminate all connections
 2620                  */
 2621                 cop = cvp->cvc_conn;
 2622                 while (cop) {
 2623                         cop2 = cop->co_next;
 2624                         atm_cm_closeconn(cop, &cvp->cvc_attr.cause.v);
 2625                         cop = cop2;
 2626                 }
 2627 
 2628                 /*
 2629                  * Terminate VCC
 2630                  */
 2631                 atm_cm_closevc(cvp);
 2632 
 2633                 break;
 2634 
 2635         case CVCS_REJECT:
 2636         case CVCS_RELEASE:
 2637         case CVCS_TERM:
 2638                 /*
 2639                  * Retry failed operation
 2640                  */
 2641                 atm_cm_closevc(cvp);
 2642                 break;
 2643 
 2644         default:
 2645 logerr:
 2646                 log(LOG_ERR,
 2647                         "atm_cm_timeout: invalid state: cvp=%p, state=%d\n",
 2648                         cvp, cvp->cvc_state);
 2649         }
 2650 }
 2651 
 2652 
 2653 /*
 2654  * CPCS User Control Commands
 2655  * 
 2656  * This function is called by an endpoint user to pass a control command
 2657  * across a CPCS data API.  Mostly we just send these down the stack.
 2658  *
 2659  * Arguments:
 2660  *      cmd     stack command code
 2661  *      cop     pointer to connection block
 2662  *      arg     argument
 2663  *
 2664  * Returns:
 2665  *      0       command output successful
 2666  *      errno   output failed - reason indicated
 2667  *
 2668  */
 2669 int
 2670 atm_cm_cpcs_ctl(cmd, cop, arg)
 2671         int             cmd;
 2672         Atm_connection  *cop;
 2673         void            *arg;
 2674 {
 2675         Atm_connvc      *cvp;
 2676         int             err = 0;
 2677 
 2678         /*
 2679          * Validate connection state
 2680          */
 2681         if (cop->co_state != COS_ACTIVE) {
 2682                 err = EFAULT;
 2683                 goto done;
 2684         }
 2685 
 2686         cvp = cop->co_connvc;
 2687         if (cvp->cvc_state != CVCS_ACTIVE) {
 2688                 err = EFAULT;
 2689                 goto done;
 2690         }
 2691 
 2692         if (cvp->cvc_attr.api != CMAPI_CPCS) {
 2693                 err = EFAULT;
 2694                 goto done;
 2695         }
 2696 
 2697         switch (cmd) {
 2698 
 2699         default:
 2700                 err = EINVAL;
 2701         }
 2702 
 2703 done:
 2704         return (err);
 2705 }
 2706 
 2707 
 2708 /*
 2709  * CPCS Data Output
 2710  * 
 2711  * This function is called by an endpoint user to output a data packet
 2712  * across a CPCS data API.   After we've validated the connection state, the
 2713  * packet will be encapsulated (if necessary) and sent down the data stack.
 2714  *
 2715  * Arguments:
 2716  *      cop     pointer to connection block
 2717  *      m       pointer to packet buffer chain to be output
 2718  *
 2719  * Returns:
 2720  *      0       packet output successful
 2721  *      errno   output failed - reason indicated
 2722  *
 2723  */
 2724 int
 2725 atm_cm_cpcs_data(cop, m)
 2726         Atm_connection  *cop;
 2727         KBuffer         *m;
 2728 {
 2729         Atm_connvc      *cvp;
 2730         struct attr_llc *llcp;
 2731         int             err, space;
 2732         void            *bp;
 2733 
 2734 
 2735         /*
 2736          * Validate connection state
 2737          */
 2738         if (cop->co_state != COS_ACTIVE) {
 2739                 err = EFAULT;
 2740                 goto done;
 2741         }
 2742 
 2743         cvp = cop->co_connvc;
 2744         if (cvp->cvc_state != CVCS_ACTIVE) {
 2745                 err = EFAULT;
 2746                 goto done;
 2747         }
 2748 
 2749         if (cvp->cvc_attr.api != CMAPI_CPCS) {
 2750                 err = EFAULT;
 2751                 goto done;
 2752         }
 2753 
 2754         /*
 2755          * Add any packet encapsulation
 2756          */
 2757         switch (cop->co_mpx) {
 2758 
 2759         case ATM_ENC_NULL:
 2760                 /*
 2761                  * None needed...
 2762                  */
 2763                 break;
 2764 
 2765         case ATM_ENC_LLC:
 2766                 /*
 2767                  * Need to add an LLC header
 2768                  */
 2769                 llcp = &cop->co_llc;
 2770 
 2771                 /*
 2772                  * See if there's room to add LLC header to front of packet.
 2773                  */
 2774                 KB_HEADROOM(m, space);
 2775                 if (space < llcp->v.llc_len) {
 2776                         KBuffer         *n;
 2777 
 2778                         /*
 2779                          * We have to allocate another buffer and tack it
 2780                          * onto the front of the packet
 2781                          */
 2782                         MGETHDR(n, KB_F_NOWAIT, KB_T_HEADER);
 2783                         if (n == 0) {
 2784                                 err = ENOMEM;
 2785                                 goto done;
 2786                         }
 2787                         KB_TAILALIGN(n, llcp->v.llc_len);
 2788                         KB_LINKHEAD(n, m);
 2789                         m = n;
 2790                 } else {
 2791                         /*
 2792                          * Header fits, just adjust buffer controls
 2793                          */
 2794                         KB_HEADADJ(m, llcp->v.llc_len);
 2795                 }
 2796 
 2797                 /*
 2798                  * Add the LLC header
 2799                  */
 2800                 KB_DATASTART(m, bp, void *);
 2801                 bcopy(llcp->v.llc_info, bp, llcp->v.llc_len);
 2802                 KB_PLENADJ(m, llcp->v.llc_len);
 2803                 break;
 2804 
 2805         default:
 2806                 panic("atm_cm_cpcs_data: mpx");
 2807         }
 2808 
 2809         /*
 2810          * Finally, we can send the packet on its way
 2811          */
 2812         STACK_CALL(CPCS_UNITDATA_INV, cvp->cvc_lower, cvp->cvc_tokl, 
 2813                 cvp, (intptr_t)m, 0, err);
 2814 
 2815 done:
 2816         return (err);
 2817 }
 2818 
 2819 
 2820 /*
 2821  * Process CPCS Stack Commands
 2822  * 
 2823  * This is the top of the CPCS API data stack.  All upward stack commands 
 2824  * for the CPCS data API will be received and processed here.
 2825  *
 2826  * Arguments:
 2827  *      cmd     stack command code
 2828  *      tok     session token (pointer to connection VCC control block)
 2829  *      arg1    argument 1
 2830  *      arg2    argument 2
 2831  *
 2832  * Returns:
 2833  *      none
 2834  *
 2835  */
 2836 static void
 2837 atm_cm_cpcs_upper(cmd, tok, arg1, arg2)
 2838         int             cmd;
 2839         void            *tok;
 2840         intptr_t        arg1;
 2841         intptr_t        arg2;
 2842 {
 2843         Atm_connection  *cop;
 2844         Atm_connvc      *cvp = tok;
 2845         KBuffer         *m;
 2846         void            *bp;
 2847         int             s;
 2848 
 2849         switch (cmd) {
 2850 
 2851         case CPCS_UNITDATA_SIG:
 2852                 /*
 2853                  * Input data packet
 2854                  */
 2855                 m = (KBuffer *)arg1;
 2856 
 2857                 if (cvp->cvc_state != CVCS_ACTIVE) {
 2858                         if (cvp->cvc_state == CVCS_ACCEPT) {
 2859                                 KBuffer *n;
 2860 
 2861                                 /*
 2862                                  * Queue up any packets received before sigmgr
 2863                                  * notifies us of incoming call completion
 2864                                  */
 2865                                 if (cvp->cvc_rcvqlen >= CVC_RCVQ_MAX) {
 2866                                         KB_FREEALL(m);
 2867                                         atm_cm_stat.cms_rcvconnvc++;
 2868                                         return;
 2869                                 }
 2870                                 KB_QNEXT(m) = NULL;
 2871                                 if (cvp->cvc_rcvq == NULL) {
 2872                                         cvp->cvc_rcvq = m;
 2873                                 } else {
 2874                                         for (n = cvp->cvc_rcvq; 
 2875                                              KB_QNEXT(n) != NULL; 
 2876                                              n = KB_QNEXT(n))
 2877                                                 ;
 2878                                         KB_QNEXT(n) = m;
 2879                                 }
 2880                                 cvp->cvc_rcvqlen++;
 2881                                 return;
 2882                         } else {
 2883                                 KB_FREEALL(m);
 2884                                 atm_cm_stat.cms_rcvconnvc++;
 2885                                 return;
 2886                         }
 2887                 }
 2888 
 2889                 /*
 2890                  * Send the packet to the interface's bpf if this
 2891                  * vc has one.
 2892                  */
 2893                 if (cvp->cvc_vcc != NULL &&
 2894                     cvp->cvc_vcc->vc_nif != NULL) {
 2895                         struct ifnet *ifp =
 2896                             (struct ifnet *)cvp->cvc_vcc->vc_nif;
 2897 
 2898                         BPF_MTAP(ifp, m);
 2899                 }
 2900 
 2901                 /*
 2902                  * Locate packet's connection
 2903                  */
 2904                 cop = cvp->cvc_conn;
 2905                 switch (cop->co_mpx) {
 2906 
 2907                 case ATM_ENC_NULL:
 2908                         /*
 2909                          * We're already there...
 2910                          */
 2911                         break;
 2912 
 2913                 case ATM_ENC_LLC:
 2914                         /*
 2915                          * Find connection with matching LLC header
 2916                          */
 2917                         if (KB_LEN(m) < T_ATM_LLC_MAX_LEN) {
 2918                                 KB_PULLUP(m, T_ATM_LLC_MAX_LEN, m);
 2919                                 if (m == 0) {
 2920                                         atm_cm_stat.cms_llcdrop++;
 2921                                         return;
 2922                                 }
 2923                         }
 2924                         KB_DATASTART(m, bp, void *);
 2925 
 2926                         s = splnet();
 2927 
 2928                         while (cop) {
 2929                                 if (bcmp(bp, cop->co_llc.v.llc_info,
 2930                                                 cop->co_llc.v.llc_len) == 0)
 2931                                         break;
 2932                                 cop = cop->co_next;
 2933                         }
 2934 
 2935                         (void) splx(s);
 2936 
 2937                         if (cop == NULL) {
 2938                                 /*
 2939                                  * No connected user for this LLC
 2940                                  */
 2941                                 KB_FREEALL(m);
 2942                                 atm_cm_stat.cms_llcid++;
 2943                                 return;
 2944                         }
 2945 
 2946                         /*
 2947                          * Strip off the LLC header
 2948                          */
 2949                         KB_HEADADJ(m, -cop->co_llc.v.llc_len);
 2950                         KB_PLENADJ(m, -cop->co_llc.v.llc_len);
 2951                         break;
 2952 
 2953                 default:
 2954                         panic("atm_cm_cpcs_upper: mpx");
 2955                 }
 2956 
 2957                 /*
 2958                  * We've found our connection, so hand the packet off
 2959                  */
 2960                 if (cop->co_state != COS_ACTIVE) {
 2961                         KB_FREEALL(m);
 2962                         atm_cm_stat.cms_rcvconn++;
 2963                         return;
 2964                 }
 2965                 (*cop->co_endpt->ep_cpcs_data)(cop->co_toku, m);
 2966                 break;
 2967 
 2968         case CPCS_UABORT_SIG:
 2969         case CPCS_PABORT_SIG:
 2970                 /*
 2971                  * We don't support these (yet), so just FALLTHROUGH
 2972                  */
 2973 
 2974         default:
 2975                 log(LOG_ERR, "atm_cm_cpcs_upper: unknown cmd 0x%x\n", cmd);
 2976         }
 2977 }
 2978 
 2979 
 2980 /*
 2981  * SAAL User Control Commands
 2982  * 
 2983  * This function is called by an endpoint user to pass a control command
 2984  * across a SAAL data API.  Mostly we just send these down the stack.
 2985  *
 2986  * Arguments:
 2987  *      cmd     stack command code
 2988  *      cop     pointer to connection block
 2989  *      arg     argument
 2990  *
 2991  * Returns:
 2992  *      0       command output successful
 2993  *      errno   output failed - reason indicated
 2994  *
 2995  */
 2996 int
 2997 atm_cm_saal_ctl(cmd, cop, arg)
 2998         int             cmd;
 2999         Atm_connection  *cop;
 3000         void            *arg;
 3001 {
 3002         Atm_connvc      *cvp;
 3003         int             err = 0;
 3004 
 3005         /*
 3006          * Validate connection state
 3007          */
 3008         if (cop->co_state != COS_ACTIVE) {
 3009                 err = EFAULT;
 3010                 goto done;
 3011         }
 3012 
 3013         cvp = cop->co_connvc;
 3014         if (cvp->cvc_state != CVCS_ACTIVE) {
 3015                 err = EFAULT;
 3016                 goto done;
 3017         }
 3018 
 3019         if (cvp->cvc_attr.api != CMAPI_SAAL) {
 3020                 err = EFAULT;
 3021                 goto done;
 3022         }
 3023 
 3024         switch (cmd) {
 3025 
 3026         case SSCF_UNI_ESTABLISH_REQ:
 3027         case SSCF_UNI_RELEASE_REQ:
 3028                 /*
 3029                  * Pass command down the stack
 3030                  */
 3031                 STACK_CALL(cmd, cvp->cvc_lower, cvp->cvc_tokl, cvp, 
 3032                         (intptr_t)arg, 0, err);
 3033                 break;
 3034 
 3035         default:
 3036                 err = EINVAL;
 3037         }
 3038 
 3039 done:
 3040         return (err);
 3041 }
 3042 
 3043 
 3044 /*
 3045  * SAAL Data Output
 3046  * 
 3047  * This function is called by an endpoint user to output a data packet
 3048  * across a SAAL data API.   After we've validated the connection state,
 3049  * the packet will be sent down the data stack.
 3050  *
 3051  * Arguments:
 3052  *      cop     pointer to connection block
 3053  *      m       pointer to packet buffer chain to be output
 3054  *
 3055  * Returns:
 3056  *      0       packet output successful
 3057  *      errno   output failed - reason indicated
 3058  *
 3059  */
 3060 int
 3061 atm_cm_saal_data(cop, m)
 3062         Atm_connection  *cop;
 3063         KBuffer         *m;
 3064 {
 3065         Atm_connvc      *cvp;
 3066         int             err;
 3067 
 3068 
 3069         /*
 3070          * Validate connection state
 3071          */
 3072         if (cop->co_state != COS_ACTIVE) {
 3073                 err = EFAULT;
 3074                 goto done;
 3075         }
 3076 
 3077         cvp = cop->co_connvc;
 3078         if (cvp->cvc_state != CVCS_ACTIVE) {
 3079                 err = EFAULT;
 3080                 goto done;
 3081         }
 3082 
 3083         if (cvp->cvc_attr.api != CMAPI_SAAL) {
 3084                 err = EFAULT;
 3085                 goto done;
 3086         }
 3087 
 3088         /*
 3089          * Finally, we can send the packet on its way
 3090          */
 3091         STACK_CALL(SSCF_UNI_DATA_REQ, cvp->cvc_lower, cvp->cvc_tokl, 
 3092                 cvp, (intptr_t)m, 0, err);
 3093 
 3094 done:
 3095         return (err);
 3096 }
 3097 
 3098 
 3099 /*
 3100  * Process SAAL Stack Commands
 3101  * 
 3102  * This is the top of the SAAL API data stack.  All upward stack commands 
 3103  * for the SAAL data API will be received and processed here.
 3104  *
 3105  * Arguments:
 3106  *      cmd     stack command code
 3107  *      tok     session token (pointer to connection VCC control block)
 3108  *      arg1    argument 1
 3109  *      arg2    argument 2
 3110  *
 3111  * Returns:
 3112  *      none
 3113  *
 3114  */
 3115 static void
 3116 atm_cm_saal_upper(cmd, tok, arg1, arg2)
 3117         int             cmd;
 3118         void            *tok;
 3119         intptr_t        arg1;
 3120         intptr_t        arg2;
 3121 {
 3122         Atm_connection  *cop;
 3123         Atm_connvc      *cvp = tok;
 3124 
 3125 
 3126         switch (cmd) {
 3127 
 3128         case SSCF_UNI_ESTABLISH_IND:
 3129         case SSCF_UNI_ESTABLISH_CNF:
 3130         case SSCF_UNI_RELEASE_IND:
 3131         case SSCF_UNI_RELEASE_CNF:
 3132                 /*
 3133                  * Control commands
 3134                  */
 3135                 cop = cvp->cvc_conn;
 3136                 if (cvp->cvc_state != CVCS_ACTIVE)
 3137                         break;
 3138                 if (cop->co_state != COS_ACTIVE)
 3139                         break;
 3140 
 3141                 (*cop->co_endpt->ep_saal_ctl)(cmd, cop->co_toku, (void *)arg1);
 3142                 break;
 3143 
 3144         case SSCF_UNI_DATA_IND:
 3145                 /*
 3146                  * User data
 3147                  */
 3148                 cop = cvp->cvc_conn;
 3149                 if (cvp->cvc_state != CVCS_ACTIVE) {
 3150                         atm_cm_stat.cms_rcvconnvc++;
 3151                         KB_FREEALL((KBuffer *)arg1);
 3152                         break;
 3153                 }
 3154                 if (cop->co_state != COS_ACTIVE) {
 3155                         atm_cm_stat.cms_rcvconn++;
 3156                         KB_FREEALL((KBuffer *)arg1);
 3157                         break;
 3158                 }
 3159 
 3160                 (*cop->co_endpt->ep_saal_data)(cop->co_toku, (KBuffer *)arg1);
 3161                 break;
 3162 
 3163         case SSCF_UNI_UNITDATA_IND:
 3164                 /*
 3165                  * Not supported
 3166                  */
 3167                 KB_FREEALL((KBuffer *)arg1);
 3168 
 3169                 /* FALLTHRU */
 3170 
 3171         default:
 3172                 log(LOG_ERR, "atm_cm_saal_upper: unknown cmd 0x%x\n", cmd);
 3173         }
 3174 }
 3175 
 3176 
 3177 /*
 3178  * SSCOP User Control Commands
 3179  * 
 3180  * This function is called by an endpoint user to pass a control command
 3181  * across a SSCOP data API.  Mostly we just send these down the stack.
 3182  *
 3183  * Arguments:
 3184  *      cmd     stack command code
 3185  *      cop     pointer to connection block
 3186  *      arg1    argument
 3187  *      arg2    argument
 3188  *
 3189  * Returns:
 3190  *      0       command output successful
 3191  *      errno   output failed - reason indicated
 3192  *
 3193  */
 3194 int
 3195 atm_cm_sscop_ctl(cmd, cop, arg1, arg2)
 3196         int             cmd;
 3197         Atm_connection  *cop;
 3198         void            *arg1;
 3199         void            *arg2;
 3200 {
 3201         Atm_connvc      *cvp;
 3202         int             err = 0;
 3203 
 3204         /*
 3205          * Validate connection state
 3206          */
 3207         if (cop->co_state != COS_ACTIVE) {
 3208                 err = EFAULT;
 3209                 goto done;
 3210         }
 3211 
 3212         cvp = cop->co_connvc;
 3213         if (cvp->cvc_state != CVCS_ACTIVE) {
 3214                 err = EFAULT;
 3215                 goto done;
 3216         }
 3217 
 3218         if (cvp->cvc_attr.api != CMAPI_SSCOP) {
 3219                 err = EFAULT;
 3220                 goto done;
 3221         }
 3222 
 3223         switch (cmd) {
 3224 
 3225         case SSCOP_ESTABLISH_REQ:
 3226         case SSCOP_ESTABLISH_RSP:
 3227         case SSCOP_RELEASE_REQ:
 3228         case SSCOP_RESYNC_REQ:
 3229         case SSCOP_RESYNC_RSP:
 3230         case SSCOP_RECOVER_RSP:
 3231         case SSCOP_RETRIEVE_REQ:
 3232                 /*
 3233                  * Pass command down the stack
 3234                  */
 3235                 STACK_CALL(cmd, cvp->cvc_lower, cvp->cvc_tokl, cvp, 
 3236                         (intptr_t)arg1, (intptr_t)arg2, err);
 3237                 break;
 3238 
 3239         default:
 3240                 err = EINVAL;
 3241         }
 3242 
 3243 done:
 3244         return (err);
 3245 }
 3246 
 3247 
 3248 /*
 3249  * SSCOP Data Output
 3250  * 
 3251  * This function is called by an endpoint user to output a data packet
 3252  * across a SSCOP data API.   After we've validated the connection state,
 3253  * the packet will be encapsulated and sent down the data stack.
 3254  *
 3255  * Arguments:
 3256  *      cop     pointer to connection block
 3257  *      m       pointer to packet buffer chain to be output
 3258  *
 3259  * Returns:
 3260  *      0       packet output successful
 3261  *      errno   output failed - reason indicated
 3262  *
 3263  */
 3264 int
 3265 atm_cm_sscop_data(cop, m)
 3266         Atm_connection  *cop;
 3267         KBuffer         *m;
 3268 {
 3269         Atm_connvc      *cvp;
 3270         int             err;
 3271 
 3272 
 3273         /*
 3274          * Validate connection state
 3275          */
 3276         if (cop->co_state != COS_ACTIVE) {
 3277                 err = EFAULT;
 3278                 goto done;
 3279         }
 3280 
 3281         cvp = cop->co_connvc;
 3282         if (cvp->cvc_state != CVCS_ACTIVE) {
 3283                 err = EFAULT;
 3284                 goto done;
 3285         }
 3286 
 3287         if (cvp->cvc_attr.api != CMAPI_SSCOP) {
 3288                 err = EFAULT;
 3289                 goto done;
 3290         }
 3291 
 3292         /*
 3293          * Finally, we can send the packet on its way
 3294          */
 3295         STACK_CALL(SSCOP_DATA_REQ, cvp->cvc_lower, cvp->cvc_tokl, 
 3296                 cvp, (intptr_t)m, 0, err);
 3297 
 3298 done:
 3299         return (err);
 3300 }
 3301 
 3302 
 3303 /*
 3304  * Process SSCOP Stack Commands
 3305  * 
 3306  * This is the top of the SSCOP API data stack.  All upward stack commands 
 3307  * for the SSCOP data API will be received and processed here.
 3308  *
 3309  * Arguments:
 3310  *      cmd     stack command code
 3311  *      tok     session token (pointer to connection VCC control block)
 3312  *      arg1    argument 1
 3313  *      arg2    argument 2
 3314  *
 3315  * Returns:
 3316  *      none
 3317  *
 3318  */
 3319 static void
 3320 atm_cm_sscop_upper(cmd, tok, arg1, arg2)
 3321         int             cmd;
 3322         void            *tok;
 3323         intptr_t        arg1;
 3324         intptr_t        arg2;
 3325 {
 3326         Atm_connection  *cop;
 3327         Atm_connvc      *cvp = tok;
 3328 
 3329         switch (cmd) {
 3330 
 3331         case SSCOP_ESTABLISH_IND:
 3332         case SSCOP_ESTABLISH_CNF:
 3333         case SSCOP_RELEASE_IND:
 3334         case SSCOP_RESYNC_IND:
 3335                 /*
 3336                  * Control commands
 3337                  */
 3338                 cop = cvp->cvc_conn;
 3339                 if ((cvp->cvc_state != CVCS_ACTIVE) ||
 3340                     (cop->co_state != COS_ACTIVE)) {
 3341                         KB_FREEALL((KBuffer *)arg1);
 3342                         break;
 3343                 }
 3344 
 3345                 (*cop->co_endpt->ep_sscop_ctl)
 3346                         (cmd, cop->co_toku, (void *)arg1, (void *)arg2);
 3347                 break;
 3348 
 3349         case SSCOP_RELEASE_CNF:
 3350         case SSCOP_RESYNC_CNF:
 3351         case SSCOP_RECOVER_IND:
 3352         case SSCOP_RETRIEVE_IND:
 3353         case SSCOP_RETRIEVECMP_IND:
 3354                 /*
 3355                  * Control commands
 3356                  */
 3357                 cop = cvp->cvc_conn;
 3358                 if ((cvp->cvc_state != CVCS_ACTIVE) ||
 3359                     (cop->co_state != COS_ACTIVE))
 3360                         break;
 3361 
 3362                 (*cop->co_endpt->ep_sscop_ctl)
 3363                         (cmd, cop->co_toku, (void *)arg1, (void *)arg2);
 3364                 break;
 3365 
 3366         case SSCOP_DATA_IND:
 3367                 /*
 3368                  * User data
 3369                  */
 3370                 cop = cvp->cvc_conn;
 3371                 if (cvp->cvc_state != CVCS_ACTIVE) {
 3372                         atm_cm_stat.cms_rcvconnvc++;
 3373                         KB_FREEALL((KBuffer *)arg1);
 3374                         break;
 3375                 }
 3376                 if (cop->co_state != COS_ACTIVE) {
 3377                         atm_cm_stat.cms_rcvconn++;
 3378                         KB_FREEALL((KBuffer *)arg1);
 3379                         break;
 3380                 }
 3381 
 3382                 (*cop->co_endpt->ep_sscop_data)
 3383                                 (cop->co_toku, (KBuffer *)arg1, arg2);
 3384                 break;
 3385 
 3386         case SSCOP_UNITDATA_IND:
 3387                 /*
 3388                  * Not supported
 3389                  */
 3390                 KB_FREEALL((KBuffer *)arg1);
 3391 
 3392                 /* FALLTHRU */
 3393 
 3394         default:
 3395                 log(LOG_ERR, "atm_cm_sscop_upper: unknown cmd 0x%x\n", cmd);
 3396         }
 3397 }
 3398 
 3399 
 3400 /*
 3401  * Register an ATM Endpoint Service
 3402  * 
 3403  * Every ATM endpoint service must register itself here before it can 
 3404  * issue or receive any connection requests.
 3405  *
 3406  * Arguments:
 3407  *      epp     pointer to endpoint definition structure
 3408  *
 3409  * Returns:
 3410  *      0       registration successful
 3411  *      errno   registration failed - reason indicated
 3412  *
 3413  */
 3414 int
 3415 atm_endpoint_register(epp)
 3416         Atm_endpoint    *epp;
 3417 {
 3418         int             s = splnet();
 3419 
 3420         /*
 3421          * See if we need to be initialized
 3422          */
 3423         if (!atm_init)
 3424                 atm_initialize();
 3425 
 3426         /*
 3427          * Validate endpoint
 3428          */
 3429         if (epp->ep_id > ENDPT_MAX) {
 3430                 (void) splx(s);
 3431                 return (EINVAL);
 3432         }
 3433         if (atm_endpoints[epp->ep_id] != NULL) {
 3434                 (void) splx(s);
 3435                 return (EEXIST);
 3436         }
 3437 
 3438         /*
 3439          * Add endpoint to list
 3440          */
 3441         atm_endpoints[epp->ep_id] = epp;
 3442 
 3443         (void) splx(s);
 3444         return (0);
 3445 }
 3446 
 3447 
 3448 /*
 3449  * De-register an ATM Endpoint Service
 3450  * 
 3451  * Each ATM endpoint service provider must de-register its registered 
 3452  * endpoint(s) before terminating.  Specifically, loaded kernel modules
 3453  * must de-register their services before unloading themselves.
 3454  *
 3455  * Arguments:
 3456  *      epp     pointer to endpoint definition structure
 3457  *
 3458  * Returns:
 3459  *      0       de-registration successful 
 3460  *      errno   de-registration failed - reason indicated
 3461  *
 3462  */
 3463 int
 3464 atm_endpoint_deregister(epp)
 3465         Atm_endpoint    *epp;
 3466 {
 3467         int     s = splnet();
 3468 
 3469         /*
 3470          * Validate endpoint
 3471          */
 3472         if (epp->ep_id > ENDPT_MAX) {
 3473                 (void) splx(s);
 3474                 return (EINVAL);
 3475         }
 3476         if (atm_endpoints[epp->ep_id] != epp) {
 3477                 (void) splx(s);
 3478                 return (ENOENT);
 3479         }
 3480 
 3481         /*
 3482          * Remove endpoint from list
 3483          */
 3484         atm_endpoints[epp->ep_id] = NULL;
 3485 
 3486         (void) splx(s);
 3487         return (0);
 3488 }
 3489 

Cache object: f7d706a90d9ccb8757bf94ebb0c27622


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.