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

Cache object: b37a8a9d4ab920d6454926bb303b0ace


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