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

Cache object: 180e9e57fcb5425bd1ec78ba08433582


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