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

Cache object: e3faa98cfbc26581279cfbb18fc3ce40


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