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_if.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  * ===================================
    4  * HARP  |  Host ATM Research Platform
    5  * ===================================
    6  *
    7  *
    8  * This Host ATM Research Platform ("HARP") file (the "Software") is
    9  * made available by Network Computing Services, Inc. ("NetworkCS")
   10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   11  * support of any kind.
   12  *
   13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   17  * In no event shall NetworkCS be responsible for any damages, including
   18  * but not limited to consequential damages, arising from or relating to
   19  * any use of the Software or related support.
   20  *
   21  * Copyright 1994-1998 Network Computing Services, Inc.
   22  *
   23  * Copies of this Software may be made, however, the above copyright
   24  * notice must be reproduced on all copies.
   25  *
   26  *      @(#) $FreeBSD$
   27  *
   28  */
   29 
   30 /*
   31  * Core ATM Services
   32  * -----------------
   33  *
   34  * ATM interface management
   35  *
   36  */
   37 
   38 #include <netatm/kern_include.h>
   39 
   40 #ifndef lint
   41 __RCSID("@(#) $FreeBSD$");
   42 #endif
   43 
   44 
   45 #if (defined(BSD) && (BSD < 199506))
   46 extern int              ifqmaxlen;
   47 #endif
   48 
   49 /*
   50  * Local functions
   51  */
   52 static int      atm_physif_ioctl __P((int, caddr_t, caddr_t));
   53 #if (defined(BSD) && (BSD >= 199306))
   54 static int      atm_netif_rtdel __P((struct radix_node *, void *));
   55 #endif
   56 static int      atm_if_ioctl __P((struct ifnet *, u_long, caddr_t));
   57 static int      atm_ifparse __P((char *, char *, int, int *));
   58 
   59 /*
   60  * Local variables
   61  */
   62 static int      (*atm_ifouttbl[AF_MAX+1])
   63                         __P((struct ifnet *, KBuffer *, struct sockaddr *))
   64                                 = {NULL};
   65 
   66 
   67 /*
   68  * Register an ATM physical interface
   69  * 
   70  * Each ATM device interface must register itself here upon completing
   71  * its internal initialization.  This applies to both linked and loaded
   72  * device drivers.  The interface must be registered before a signalling
   73  * manager can be attached.
   74  *
   75  * Arguments:
   76  *      cup     pointer to interface's common unit structure
   77  *      name    pointer to device name string
   78  *      sdp     pointer to interface's stack services
   79  *
   80  * Returns:
   81  *      0       registration successful
   82  *      errno   registration failed - reason indicated
   83  *
   84  */
   85 int
   86 atm_physif_register(cup, name, sdp)
   87         Cmn_unit                *cup;
   88         char                    *name;
   89         struct stack_defn       *sdp;
   90 {
   91         struct atm_pif  *pip;
   92         int             s;
   93 
   94         /*
   95          * See if we need to be initialized
   96          */
   97         if (!atm_init)
   98                 atm_initialize();
   99 
  100         /*
  101          * Make sure we're not already registered
  102          */
  103         if (cup->cu_flags & CUF_REGISTER) {
  104                 return (EALREADY);
  105         }
  106 
  107         s = splnet();
  108 
  109         /*
  110          * Make sure an interface is only registered once
  111          */
  112         for (pip = atm_interface_head; pip != NULL; pip = pip->pif_next) {
  113                 if ((cup->cu_unit == pip->pif_unit) && 
  114                     (strcmp(name, pip->pif_name) == 0)) {
  115                         (void) splx(s);
  116                         return (EEXIST);
  117                 }
  118         }
  119 
  120         /*
  121          * Fill in physical interface parameters
  122          */
  123         pip = &cup->cu_pif;
  124         pip->pif_name = name;
  125         pip->pif_unit = cup->cu_unit;
  126         pip->pif_flags = PIF_UP;
  127         pip->pif_services = sdp;
  128         pip->pif_ioctl = atm_physif_ioctl;
  129 
  130         /*
  131          * Link in the interface and mark us registered
  132          */
  133         LINK2TAIL(pip, struct atm_pif, atm_interface_head, pif_next);
  134         cup->cu_flags |= CUF_REGISTER;
  135 
  136         (void) splx(s);
  137         return (0);
  138 }
  139 
  140 
  141 /*
  142  * De-register an ATM physical interface
  143  * 
  144  * Each ATM interface must de-register itself before downing the interface.  
  145  * The interface's signalling manager will be detached and any network
  146  * interface and VCC control blocks will be freed.  
  147  *
  148  * Arguments:
  149  *      cup     pointer to interface's common unit structure
  150  *
  151  * Returns:
  152  *      0       de-registration successful
  153  *      errno   de-registration failed - reason indicated
  154  *
  155  */
  156 int
  157 atm_physif_deregister(cup)
  158         Cmn_unit        *cup;
  159 {
  160         struct atm_pif  *pip = (struct atm_pif *)&cup->cu_pif;
  161         Cmn_vcc         *cvp;
  162         int     err;
  163         int     s = splnet();
  164 
  165         /*
  166          * Detach and deregister, if needed
  167          */
  168         if ((cup->cu_flags & CUF_REGISTER)) {
  169 
  170                 /*
  171                  * Detach from signalling manager
  172                  */
  173                 if (pip->pif_sigmgr != NULL) {
  174                         err = atm_sigmgr_detach(pip);
  175                         if (err && (err != ENOENT)) {
  176                                 (void) splx(s);
  177                                 return (err);
  178                         }
  179                 }
  180 
  181                 /*
  182                  * Make sure signalling manager is detached
  183                  */
  184                 if (pip->pif_sigmgr != NULL) {
  185                         (void) splx(s);
  186                         return (EBUSY);
  187                 }
  188 
  189                 /*
  190                  * Unlink interface
  191                  */
  192                 UNLINK(pip, struct atm_pif, atm_interface_head, pif_next);
  193 
  194                 cup->cu_flags &= ~CUF_REGISTER;
  195         }
  196 
  197         /*
  198          * Free all of our network interfaces
  199          */
  200         atm_physif_freenifs(pip);
  201 
  202         /*
  203          * Free unit's vcc information
  204          */
  205         cvp = cup->cu_vcc;
  206         while (cvp) {
  207                 atm_free(cvp);
  208                 cvp = cvp->cv_next;
  209         }
  210         cup->cu_vcc = (Cmn_vcc *)NULL;
  211 
  212         (void) splx(s);
  213 
  214         return (0);
  215 }
  216 
  217 
  218 /*
  219  * Free all network interfaces on a physical interface
  220  *
  221  * Arguments
  222  *      pip             pointer to physical interface structure
  223  *
  224  * Returns
  225  *      none
  226  *
  227  */
  228 void
  229 atm_physif_freenifs(pip)
  230         struct atm_pif  *pip;
  231 {
  232         struct atm_nif  *nip = pip->pif_nif;
  233         int     s = splnet();
  234 
  235         while ( nip ) 
  236         {
  237                 /*
  238                  * atm_nif_detach zeros pointers - save so we can
  239                  * walk the chain.
  240                  */
  241                 struct atm_nif  *nipp = nip->nif_pnext;
  242 
  243                 /*
  244                  * Clean up network i/f trails
  245                  */
  246                 atm_nif_detach ( nip );
  247                 atm_free ((caddr_t)nip);
  248                 nip = nipp;
  249         }
  250         pip->pif_nif = (struct atm_nif *)NULL;
  251 
  252         (void) splx(s);
  253 
  254         return;
  255 }
  256 
  257 
  258 /*
  259  * Handle physical interface ioctl's
  260  *
  261  * See <netatm/atm_ioctl.h> for definitions.
  262  *
  263  * Called at splnet.
  264  *
  265  * Arguments:
  266  *      code                    Ioctl function (sub)code
  267  *      data                    Data block. On input contains command,
  268  *                                      on output, contains results
  269  *      arg                     Optional code specific arguments
  270  *
  271  * Returns:
  272  *      0                       Request processed successfully
  273  *      errno                   Request failed - reason code
  274  *
  275  */
  276 static int
  277 atm_physif_ioctl(code, data, arg)
  278         int     code;
  279         caddr_t data;
  280         caddr_t arg;
  281 {
  282         struct atminfreq        *aip = (struct atminfreq *)data;
  283         struct atmsetreq        *asr = (struct atmsetreq *)data;
  284         struct atm_pif          *pip;
  285         struct atm_nif          *nip;
  286         struct sigmgr           *smp;
  287         struct siginst          *sip;
  288         struct ifnet            *ifp;
  289         Cmn_unit                *cup;
  290         Atm_config              *acp;
  291         caddr_t                 buf = aip->air_buf_addr;
  292         struct air_phy_stat_rsp *apsp;
  293         struct air_int_rsp      apr;
  294         struct air_netif_rsp    anr;
  295         struct air_cfg_rsp      acr;
  296         int                     count, len, buf_len = aip->air_buf_len;
  297         int                     err = 0;
  298         char                    ifname[2*IFNAMSIZ];
  299 #if (defined(BSD) && (BSD >= 199103))
  300         struct ifaddr           *ifa;
  301         struct in_ifaddr        *ia;
  302         struct sockaddr_dl      *sdl;
  303 #endif
  304  
  305 
  306         switch ( aip->air_opcode ) {
  307 
  308         case AIOCS_INF_INT:
  309                 /*
  310                  * Get physical interface information
  311                  */
  312                 aip = (struct atminfreq *)data;
  313                 pip = (struct atm_pif *)arg;
  314 
  315                 /*
  316                  * Make sure there's room in user buffer
  317                  */
  318                 if (aip->air_buf_len < sizeof(apr)) {
  319                         err = ENOSPC;
  320                         break;
  321                 }
  322 
  323                 /*
  324                  * Fill in info to be returned
  325                  */
  326                 KM_ZERO((caddr_t)&apr, sizeof(apr));
  327                 smp = pip->pif_sigmgr;
  328                 sip = pip->pif_siginst;
  329                 (void) snprintf(apr.anp_intf, sizeof(apr.anp_intf),
  330                         "%s%d", pip->pif_name, pip->pif_unit );
  331                 if ( pip->pif_nif )
  332                 {
  333                         strcpy(apr.anp_nif_pref, pip->pif_nif->nif_if.if_name);
  334 
  335                         nip = pip->pif_nif;
  336                         while ( nip ) {
  337                                 apr.anp_nif_cnt++;
  338                                 nip = nip->nif_pnext;
  339                         }
  340                 }
  341                 if (sip) {
  342                         ATM_ADDR_COPY(&sip->si_addr, &apr.anp_addr);
  343                         ATM_ADDR_COPY(&sip->si_subaddr, &apr.anp_subaddr);
  344                         apr.anp_sig_proto = smp->sm_proto;
  345                         apr.anp_sig_state = sip->si_state;
  346                 }
  347 
  348                 /*
  349                  * Copy data to user buffer
  350                  */
  351                 err = copyout((caddr_t)&apr, aip->air_buf_addr, sizeof(apr));
  352                 if (err)
  353                         break;
  354 
  355                 /*
  356                  * Update buffer pointer/count
  357                  */
  358                 aip->air_buf_addr += sizeof(apr);
  359                 aip->air_buf_len -= sizeof(apr);
  360                 break;
  361 
  362         case AIOCS_INF_NIF:
  363                 /*
  364                  * Get network interface information
  365                  */
  366                 aip = (struct atminfreq *)data;
  367                 nip = (struct atm_nif *)arg;
  368                 ifp = &nip->nif_if;
  369                 pip = nip->nif_pif;
  370 
  371                 /*
  372                  * Make sure there's room in user buffer
  373                  */
  374                 if (aip->air_buf_len < sizeof(anr)) {
  375                         err = ENOSPC;
  376                         break;
  377                 }
  378 
  379                 /*
  380                  * Fill in info to be returned
  381                  */
  382                 KM_ZERO((caddr_t)&anr, sizeof(anr));
  383                 (void) snprintf(anr.anp_intf, sizeof(anr.anp_intf),
  384                     "%s%d", ifp->if_name, ifp->if_unit);
  385                 IFP_TO_IA(ifp, ia);
  386                 if (ia) {
  387                         anr.anp_proto_addr = *ia->ia_ifa.ifa_addr;
  388                 }
  389                 (void) snprintf(anr.anp_phy_intf, sizeof(anr.anp_phy_intf),
  390                     "%s%d", pip->pif_name, pip->pif_unit);
  391 
  392                 /*
  393                  * Copy data to user buffer
  394                  */
  395                 err = copyout((caddr_t)&anr, aip->air_buf_addr, sizeof(anr));
  396                 if (err)
  397                         break;
  398 
  399                 /*
  400                  * Update buffer pointer/count
  401                  */
  402                 aip->air_buf_addr += sizeof(anr);
  403                 aip->air_buf_len -= sizeof(anr);
  404                 break;
  405 
  406         case AIOCS_INF_PIS:
  407                 /*
  408                  * Get per interface statistics
  409                  */
  410                 pip = (struct atm_pif *)arg;
  411                 if ( pip == NULL )
  412                         return ( ENXIO );
  413                 snprintf ( ifname, sizeof(ifname),
  414                     "%s%d", pip->pif_name, pip->pif_unit );
  415 
  416                 /*
  417                  * Cast response into users buffer
  418                  */
  419                 apsp = (struct air_phy_stat_rsp *)buf;
  420 
  421                 /*
  422                  * Sanity check
  423                  */
  424                 len = sizeof ( struct air_phy_stat_rsp );
  425                 if ( buf_len < len )
  426                         return ( ENOSPC );
  427 
  428                 /*
  429                  * Copy interface name into response
  430                  */
  431                 if ( err = copyout ( ifname, apsp->app_intf, IFNAMSIZ ) )
  432                         break;
  433 
  434                 /*
  435                  * Copy counters
  436                  */
  437                 if ( err = copyout ( &pip->pif_ipdus, &apsp->app_ipdus,
  438                     len - sizeof ( apsp->app_intf ) ) )
  439                         break;
  440 
  441                 /*
  442                  * Adjust buffer elements
  443                  */
  444                 buf += len;
  445                 buf_len -= len;
  446 
  447                 aip->air_buf_addr = buf;
  448                 aip->air_buf_len = buf_len;
  449                 break;
  450 
  451         case AIOCS_SET_NIF:
  452                 /*
  453                  * Set NIF - allow user to configure 1 or more logical
  454                  *      interfaces per physical interface.
  455                  */
  456 
  457                 /*
  458                  * Get pointer to physical interface structure from
  459                  * ioctl argument.
  460                  */
  461                 pip = (struct atm_pif *)arg;
  462                 cup = (Cmn_unit *)pip;
  463 
  464                 /*
  465                  * Sanity check - are we already connected to something?
  466                  */
  467                 if ( pip->pif_sigmgr )
  468                 {
  469                         err = EBUSY;
  470                         break;
  471                 }
  472 
  473                 /*
  474                  * Free any previously allocated NIFs
  475                  */
  476                 atm_physif_freenifs(pip);
  477 
  478                 /*
  479                  * Add list of interfaces
  480                  */
  481                 for ( count = 0; count < asr->asr_nif_cnt; count++ )
  482                 {
  483                         nip = (struct atm_nif *)atm_allocate(cup->cu_nif_pool);
  484                         if ( nip == NULL )
  485                         {
  486                                 /*
  487                                  * Destroy any successful nifs
  488                                  */
  489                                 atm_physif_freenifs(pip);
  490                                 err = ENOMEM;
  491                                 break;
  492                         }
  493 
  494                         nip->nif_pif = pip;
  495                         ifp = &nip->nif_if;
  496 
  497                         strcpy ( nip->nif_name, asr->asr_nif_pref );
  498                         nip->nif_sel = count;
  499 
  500                         ifp->if_name = nip->nif_name;
  501                         ifp->if_unit = count;
  502                         ifp->if_mtu = ATM_NIF_MTU;
  503                         ifp->if_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
  504                         ifp->if_output = atm_ifoutput;
  505                         ifp->if_ioctl = atm_if_ioctl;
  506                         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  507 #if (defined(BSD) && (BSD >= 199103))
  508                         /*
  509                          * Set if_type and if_baudrate
  510                          */
  511                         ifp->if_type = IFT_ATM;
  512                         switch ( cup->cu_config.ac_media ) {
  513                         case MEDIA_TAXI_100:
  514                                 ifp->if_baudrate = 100000000;
  515                                 break;
  516                         case MEDIA_TAXI_140:
  517                                 ifp->if_baudrate = 140000000;
  518                                 break;
  519                         case MEDIA_OC3C:
  520                         case MEDIA_OC12C:
  521                         case MEDIA_UTP155:
  522                                 ifp->if_baudrate = 155000000;
  523                                 break;
  524                         }
  525 #endif
  526 
  527                         if ( err = atm_nif_attach ( nip ) )
  528                         {
  529                                 atm_free ( (caddr_t)nip );
  530 
  531                                 /*
  532                                  * Destroy any successful nifs
  533                                  */
  534                                 atm_physif_freenifs(pip);
  535                                 break;
  536                         }
  537 #if (defined(BSD) && (BSD >= 199103))
  538                         /*
  539                          * Set macaddr in <Link> address
  540                          */
  541                         ifp->if_addrlen = 6;
  542                         ifa = ifnet_addrs[ifp->if_index - 1];
  543                         if ( ifa ) {
  544                                 sdl = (struct sockaddr_dl *)
  545                                         ifa->ifa_addr;
  546                                 sdl->sdl_type = IFT_ETHER;
  547                                 sdl->sdl_alen = ifp->if_addrlen;
  548                                 bcopy ( (caddr_t)&cup->cu_config.ac_macaddr,
  549                                         LLADDR(sdl), ifp->if_addrlen );
  550                         }
  551 #endif
  552                 }
  553                 break;
  554 
  555         case AIOCS_INF_CFG:
  556                 /*
  557                  * Get adapter configuration information
  558                  */
  559                 aip = (struct atminfreq *)data;
  560                 pip = (struct atm_pif *)arg;
  561                 cup = (Cmn_unit *)pip;
  562                 acp = &cup->cu_config;
  563 
  564                 /*
  565                  * Make sure there's room in user buffer
  566                  */
  567                 if (aip->air_buf_len < sizeof(acr)) {
  568                         err = ENOSPC;
  569                         break;
  570                 }
  571 
  572                 /*
  573                  * Fill in info to be returned
  574                  */
  575                 KM_ZERO((caddr_t)&acr, sizeof(acr));
  576                 (void) snprintf(acr.acp_intf, sizeof(acr.acp_intf),
  577                     "%s%d", pip->pif_name, pip->pif_unit);
  578                 KM_COPY((caddr_t)acp, (caddr_t)&acr.acp_cfg,
  579                                 sizeof(Atm_config));
  580 
  581                 /*
  582                  * Copy data to user buffer
  583                  */
  584                 err = copyout((caddr_t)&acr, aip->air_buf_addr,
  585                                 sizeof(acr));
  586                 if (err)
  587                         break;
  588 
  589                 /*
  590                  * Update buffer pointer/count
  591                  */
  592                 aip->air_buf_addr += sizeof(acr);
  593                 aip->air_buf_len -= sizeof(acr);
  594                 break;
  595 
  596         case AIOCS_INF_VST:
  597                 /*
  598                  * Pass off to device-specific handler
  599                  */
  600                 cup = (Cmn_unit *)arg;
  601                 if (cup == NULL)
  602                         err = ENXIO;
  603                 else
  604                         err = (*cup->cu_ioctl)(code, data, arg);
  605                 break;
  606 
  607         default:
  608                 err = ENOSYS;
  609         }
  610 
  611         return ( err );
  612 }
  613 
  614 
  615 /*
  616  * Register a Network Convergence Module
  617  * 
  618  * Each ATM network convergence module must register itself here before
  619  * it will receive network interface status notifications. 
  620  *
  621  * Arguments:
  622  *      ncp     pointer to network convergence definition structure
  623  *
  624  * Returns:
  625  *      0       registration successful
  626  *      errno   registration failed - reason indicated
  627  *
  628  */
  629 int
  630 atm_netconv_register(ncp)
  631         struct atm_ncm  *ncp;
  632 {
  633         struct atm_ncm  *tdp;
  634         int             s = splnet();
  635 
  636         /*
  637          * See if we need to be initialized
  638          */
  639         if (!atm_init)
  640                 atm_initialize();
  641 
  642         /*
  643          * Validate protocol family
  644          */
  645         if (ncp->ncm_family > AF_MAX) {
  646                 (void) splx(s);
  647                 return (EINVAL);
  648         }
  649 
  650         /*
  651          * Ensure no duplicates
  652          */
  653         for (tdp = atm_netconv_head; tdp != NULL; tdp = tdp->ncm_next) {
  654                 if (tdp->ncm_family == ncp->ncm_family) {
  655                         (void) splx(s);
  656                         return (EEXIST);
  657                 }
  658         }
  659 
  660         /*
  661          * Add module to list
  662          */
  663         LINK2TAIL(ncp, struct atm_ncm, atm_netconv_head, ncm_next);
  664 
  665         /*
  666          * Add new interface output function
  667          */
  668         atm_ifouttbl[ncp->ncm_family] = ncp->ncm_ifoutput;
  669 
  670         (void) splx(s);
  671         return (0);
  672 }
  673 
  674 
  675 /*
  676  * De-register an ATM Network Convergence Module
  677  * 
  678  * Each ATM network convergence provider must de-register its registered 
  679  * service(s) before terminating.  Specifically, loaded kernel modules
  680  * must de-register their services before unloading themselves.
  681  *
  682  * Arguments:
  683  *      ncp     pointer to network convergence definition structure
  684  *
  685  * Returns:
  686  *      0       de-registration successful 
  687  *      errno   de-registration failed - reason indicated
  688  *
  689  */
  690 int
  691 atm_netconv_deregister(ncp)
  692         struct atm_ncm  *ncp;
  693 {
  694         int     found, s = splnet();
  695 
  696         /*
  697          * Remove module from list
  698          */
  699         UNLINKF(ncp, struct atm_ncm, atm_netconv_head, ncm_next, found);
  700 
  701         if (!found) {
  702                 (void) splx(s);
  703                 return (ENOENT);
  704         }
  705 
  706         /*
  707          * Remove module's interface output function
  708          */
  709         atm_ifouttbl[ncp->ncm_family] = NULL;
  710 
  711         (void) splx(s);
  712         return (0);
  713 }
  714 
  715 
  716 /*
  717  * Attach an ATM Network Interface
  718  * 
  719  * Before an ATM network interface can be used by the system, the owning
  720  * device interface must attach the network interface using this function.
  721  * The physical interface for this network interface must have been previously
  722  * registered (using atm_interface_register).  The network interface will be
  723  * added to the kernel's interface list and to the physical interface's list.
  724  * The caller is responsible for initializing the control block fields.
  725  *
  726  * Arguments:
  727  *      nip     pointer to atm network interface control block
  728  *
  729  * Returns:
  730  *      0       attach successful
  731  *      errno   attach failed - reason indicated
  732  *
  733  */
  734 int
  735 atm_nif_attach(nip)
  736         struct atm_nif  *nip;
  737 {
  738         struct atm_pif  *pip, *pip2;
  739         struct ifnet    *ifp;
  740         struct atm_ncm  *ncp;
  741         int             s;
  742 
  743         ifp = &nip->nif_if;
  744         pip = nip->nif_pif;
  745 
  746         s = splimp();
  747 
  748         /*
  749          * Verify physical interface is registered
  750          */
  751         for (pip2 = atm_interface_head; pip2 != NULL; pip2 = pip2->pif_next) {
  752                 if (pip == pip2)
  753                         break;
  754         }
  755         if ((pip == NULL) || (pip2 == NULL)) {
  756                 (void) splx(s);
  757                 return (EFAULT);
  758         }
  759 
  760         /*
  761          * Add to system interface list 
  762          */
  763         if_attach(ifp);
  764 
  765         /*
  766          * Add to physical interface list
  767          */
  768         LINK2TAIL(nip, struct atm_nif, pip->pif_nif, nif_pnext);
  769 
  770         /*
  771          * Notify network convergence modules of new network i/f
  772          */
  773         for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
  774                 int     err;
  775 
  776                 err = (*ncp->ncm_stat)(NCM_ATTACH, nip, 0);
  777                 if (err) {
  778                         atm_nif_detach(nip);
  779                         (void) splx(s);
  780                         return (err);
  781                 }
  782         }
  783 
  784         (void) splx(s);
  785         return (0);
  786 }
  787 
  788 
  789 /*
  790  * Detach an ATM Network Interface
  791  * 
  792  * Before an ATM network interface control block can be freed, all kernel
  793  * references to/from this block must be released.  This function will delete
  794  * all routing references to the interface and free all interface addresses
  795  * for the interface.  The network interface will then be removed from the
  796  * kernel's interface list and from the owning physical interface's list.
  797  * The caller is responsible for free'ing the control block.
  798  *
  799  * Arguments:
  800  *      nip     pointer to atm network interface control block
  801  *
  802  * Returns:
  803  *      none
  804  *
  805  */
  806 void
  807 atm_nif_detach(nip)
  808         struct atm_nif  *nip;
  809 {
  810         struct atm_ncm  *ncp;
  811         int             s, i;
  812         struct ifnet    *ifp = &nip->nif_if;
  813         struct ifaddr   *ifa;
  814         struct in_ifaddr        *ia;
  815         struct radix_node_head  *rnh;
  816 
  817 
  818         s = splimp();
  819 
  820         /*
  821          * Notify convergence modules of network i/f demise
  822          */
  823         for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
  824                 (void) (*ncp->ncm_stat)(NCM_DETACH, nip, 0);
  825         }
  826 
  827         /*
  828          * Mark interface down
  829          */
  830         if_down(ifp);
  831 
  832         /*
  833          * Free all interface routes and addresses
  834          */
  835         while (1) {
  836                 IFP_TO_IA(ifp, ia);
  837                 if (ia == NULL)
  838                         break;
  839 
  840                 /* Delete interface route */
  841                 in_ifscrub(ifp, ia);
  842 
  843                 /* Remove interface address from queues */
  844                 ifa = &ia->ia_ifa;
  845                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
  846                 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
  847 
  848                 /* Free interface address */
  849                 IFAFREE(ifa);
  850         }
  851 
  852         /*
  853          * Delete all remaining routes using this interface
  854          * Unfortuneatly the only way to do this is to slog through
  855          * the entire routing table looking for routes which point
  856          * to this interface...oh well...
  857          */
  858         for (i = 1; i <= AF_MAX; i++) {
  859                 if ((rnh = rt_tables[i]) == NULL)
  860                         continue;
  861                 (void) rnh->rnh_walktree(rnh, atm_netif_rtdel, ifp);
  862         }
  863 
  864         /*
  865          * Remove from system interface list (ie. if_detach())
  866          */
  867         TAILQ_REMOVE(&ifnet, ifp, if_link);
  868 
  869         /*
  870          * Remove from physical interface list
  871          */
  872         UNLINK(nip, struct atm_nif, nip->nif_pif->pif_nif, nif_pnext);
  873 
  874         (void) splx(s);
  875 }
  876 
  877 
  878 /*
  879  * Delete Routes for a Network Interface
  880  * 
  881  * Called for each routing entry via the rnh->rnh_walktree() call above
  882  * to delete all route entries referencing a detaching network interface.
  883  *
  884  * Arguments:
  885  *      rn      pointer to node in the routing table
  886  *      arg     argument passed to rnh->rnh_walktree() - detaching interface
  887  *
  888  * Returns:
  889  *      0       successful
  890  *      errno   failed - reason indicated
  891  *
  892  */
  893 static int
  894 atm_netif_rtdel(rn, arg)
  895         struct radix_node       *rn;
  896         void                    *arg;
  897 {
  898         struct rtentry  *rt = (struct rtentry *)rn;
  899         struct ifnet    *ifp = arg;
  900         int             err;
  901 
  902         if (rt->rt_ifp == ifp) {
  903 
  904                 /*
  905                  * Protect (sorta) against walktree recursion problems
  906                  * with cloned routes
  907                  */
  908                 if ((rt->rt_flags & RTF_UP) == 0)
  909                         return (0);
  910 
  911                 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
  912                                 rt_mask(rt), rt->rt_flags,
  913                                 (struct rtentry **) NULL);
  914                 if (err) {
  915                         log(LOG_WARNING, "atm_netif_rtdel: error %d\n", err);
  916                 }
  917         }
  918 
  919         return (0);
  920 }
  921 
  922 
  923 /*
  924  * Set an ATM Network Interface address
  925  * 
  926  * This is called from a device interface when processing an SIOCSIFADDR
  927  * ioctl request.  We just notify all convergence modules of the new address
  928  * and hope everyone has non-overlapping interests, since if someone reports
  929  * an error we don't go back and tell everyone to undo the change.
  930  *
  931  * Arguments:
  932  *      nip     pointer to atm network interface control block
  933  *      ifa     pointer to new interface address
  934  *
  935  * Returns:
  936  *      0       set successful
  937  *      errno   set failed - reason indicated
  938  *
  939  */
  940 int
  941 atm_nif_setaddr(nip, ifa)
  942         struct atm_nif  *nip;
  943         struct ifaddr   *ifa;
  944 {
  945         struct atm_ncm  *ncp;
  946         int     err = 0, s = splnet();
  947 
  948         /*
  949          * Notify convergence modules of network i/f change
  950          */
  951         for (ncp = atm_netconv_head; ncp; ncp = ncp->ncm_next) {
  952                 err = (*ncp->ncm_stat)(NCM_SETADDR, nip, (int)ifa);
  953                 if (err)
  954                         break;
  955         }
  956         (void) splx(s);
  957 
  958         return (err);
  959 }
  960 
  961 
  962 /*
  963  * ATM Interface Packet Output
  964  * 
  965  * All ATM network interfaces must have their ifnet if_output address set to
  966  * this function.  Since no existing network layer code is to be modified 
  967  * for ATM support, this function serves as the hook to allow network output
  968  * packets to be assigned to their proper outbound VCC.  Each network address
  969  * family which is to be supported over ATM must be assigned an output
  970  * packet processing function via atm_netconv_register().
  971  *
  972  * Arguments:
  973  *      ifp     pointer to ifnet structure
  974  *      m       pointer to packet buffer chain to be output
  975  *      dst     pointer to packet's network destination address
  976  *
  977  * Returns:
  978  *      0       packet queued to interface
  979  *      errno   output failed - reason indicated
  980  *
  981  */
  982 int
  983 #if (defined(BSD) && (BSD >= 199103))
  984 atm_ifoutput(ifp, m, dst, rt)
  985 #else
  986 atm_ifoutput(ifp, m, dst)
  987 #endif
  988         struct ifnet    *ifp;
  989         KBuffer         *m;
  990         struct sockaddr *dst;
  991 #if (defined(BSD) && (BSD >= 199103))
  992         struct rtentry  *rt;
  993 #endif
  994 {
  995         u_short         fam = dst->sa_family;
  996         int             (*func)__P((struct ifnet *, KBuffer *,
  997                                         struct sockaddr *));
  998 
  999         /*
 1000          * Validate address family
 1001          */
 1002         if (fam > AF_MAX) {
 1003                 KB_FREEALL(m);
 1004                 return (EAFNOSUPPORT);
 1005         }
 1006 
 1007         /*
 1008          * Hand packet off for dst-to-VCC mapping
 1009          */
 1010         func = atm_ifouttbl[fam];
 1011         if (func == NULL) {
 1012                 KB_FREEALL(m);
 1013                 return (EAFNOSUPPORT);
 1014         }
 1015         return ((*func)(ifp, m, dst));
 1016 }
 1017 
 1018 
 1019 /*
 1020  * Handle interface ioctl requests. 
 1021  *
 1022  * Arguments:
 1023  *      ifp             pointer to network interface structure
 1024  *      cmd             IOCTL cmd
 1025  *      data            arguments to/from ioctl
 1026  *
 1027  * Returns:
 1028  *      error           errno value
 1029  */
 1030 static int
 1031 atm_if_ioctl(ifp, cmd, data)
 1032         struct ifnet *ifp;
 1033         u_long  cmd;
 1034         caddr_t data;
 1035 {
 1036         register struct ifreq *ifr = (struct ifreq *)data;
 1037         struct atm_nif  *nip = (struct atm_nif *)ifp;
 1038         int     error = 0;
 1039         int     s = splnet();
 1040 
 1041         switch ( cmd )
 1042         {
 1043         case SIOCGIFADDR:
 1044                 KM_COPY ( (caddr_t)&(nip->nif_pif->pif_macaddr),
 1045                         (caddr_t)ifr->ifr_addr.sa_data, 
 1046                         sizeof(struct mac_addr) );
 1047                 break;
 1048 
 1049         case SIOCSIFADDR:
 1050                 error = atm_nif_setaddr ( nip, (struct ifaddr *)data);
 1051                 ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_BROADCAST;
 1052                 break;
 1053 
 1054         case SIOCGIFFLAGS:
 1055                 *(short *)data = ifp->if_flags;
 1056                 break;
 1057 
 1058         case SIOCSIFFLAGS:
 1059                 break;
 1060 
 1061         default:
 1062                 error = EINVAL;
 1063                 break;
 1064         }
 1065 
 1066         (void) splx(s);
 1067         return ( error );
 1068 }
 1069 
 1070 
 1071 /*
 1072  * Parse interface name
 1073  * 
 1074  * Parses an interface name string into a name and a unit component.
 1075  *
 1076  * Arguments:
 1077  *      name    pointer to interface name string
 1078  *      namep   address to store interface name
 1079  *      size    size available at namep
 1080  *      unitp   address to store interface unit number
 1081  *
 1082  * Returns:
 1083  *      0       name parsed
 1084  *      else    parse error
 1085  *
 1086  */
 1087 static int
 1088 atm_ifparse(name, namep, size, unitp)
 1089         char            *name;
 1090         char            *namep;
 1091         int             size;
 1092         int             *unitp;
 1093 {
 1094         char            *cp, *np;
 1095         int             len = 0, unit = 0;
 1096 
 1097         /*
 1098          * Separate supplied string into name and unit parts.
 1099          */
 1100         cp = name;
 1101         np = namep;
 1102         while (*cp) {
 1103                 if (*cp >= '' && *cp <= '9')
 1104                         break;
 1105                 if (++len >= size)
 1106                         return (-1);
 1107                 *np++ = *cp++;
 1108         }
 1109         *np = '\0';
 1110         while (*cp && *cp >= '' && *cp <= '9')
 1111                 unit = 10 * unit + *cp++ - '';
 1112 
 1113         *unitp = unit;
 1114 
 1115         return (0);
 1116 }
 1117 
 1118 
 1119 /*
 1120  * Locate ATM physical interface via name
 1121  * 
 1122  * Uses the supplied interface name string to locate a registered
 1123  * ATM physical interface.
 1124  *
 1125  * Arguments:
 1126  *      name    pointer to interface name string
 1127  *
 1128  * Returns:
 1129  *      0       interface not found
 1130  *      else    pointer to atm physical interface structure
 1131  *
 1132  */
 1133 struct atm_pif *
 1134 atm_pifname(name)
 1135         char            *name;
 1136 {
 1137         struct atm_pif  *pip;
 1138         char            n[IFNAMSIZ];
 1139         int             unit;
 1140 
 1141         /*
 1142          * Break down name
 1143          */
 1144         if (atm_ifparse(name, n, sizeof(n), &unit))
 1145                 return ((struct atm_pif *)0);
 1146 
 1147         /*
 1148          * Look for the physical interface
 1149          */
 1150         for (pip = atm_interface_head; pip; pip = pip->pif_next) {
 1151                 if ((pip->pif_unit == unit) && (strcmp(pip->pif_name, n) == 0))
 1152                         break;
 1153         }
 1154 
 1155         return (pip);
 1156 }
 1157 
 1158 
 1159 /*
 1160  * Locate ATM network interface via name
 1161  * 
 1162  * Uses the supplied interface name string to locate an ATM network interface.
 1163  *
 1164  * Arguments:
 1165  *      name    pointer to interface name string
 1166  *
 1167  * Returns:
 1168  *      0       interface not found
 1169  *      else    pointer to atm network interface structure
 1170  *
 1171  */
 1172 struct atm_nif *
 1173 atm_nifname(name)
 1174         char            *name;
 1175 {
 1176         struct atm_pif  *pip;
 1177         struct atm_nif  *nip;
 1178         char            n[IFNAMSIZ];
 1179         int             unit;
 1180 
 1181         /*
 1182          * Break down name
 1183          */
 1184         if (atm_ifparse(name, n, sizeof(n), &unit))
 1185                 return ((struct atm_nif *)0);
 1186 
 1187         /*
 1188          * Search thru each physical interface
 1189          */
 1190         for (pip = atm_interface_head; pip; pip = pip->pif_next) {
 1191                 /*
 1192                  * Looking for network interface
 1193                  */
 1194                 for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) {
 1195                         struct ifnet    *ifp = (struct ifnet *)nip;
 1196                         if ((ifp->if_unit == unit) && 
 1197                             (strcmp(ifp->if_name, n) == 0))
 1198                                 return (nip);
 1199                 }
 1200         }
 1201         return (NULL);
 1202 }
 1203 

Cache object: 95b5c2ca4be4ad404ca63974a81354c1


[ 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.