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

Cache object: 1efb2d35769267f453a90dd87fdcd497


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