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

Cache object: ba527b8e7e99fe824a4b939afd1dec2d


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