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/netinet/sctp_bsd_addr.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  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions are met:
    6  *
    7  * a) Redistributions of source code must retain the above copyright notice,
    8  *   this list of conditions and the following disclaimer.
    9  *
   10  * b) Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in
   12  *   the documentation and/or other materials provided with the distribution.
   13  *
   14  * c) Neither the name of Cisco Systems, Inc. nor the names of its
   15  *    contributors may be used to endorse or promote products derived
   16  *    from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   28  * THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /* $KAME: sctp_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include <netinet/sctp_os.h>
   37 #include <netinet/sctp_var.h>
   38 #include <netinet/sctp_pcb.h>
   39 #include <netinet/sctp_header.h>
   40 #include <netinet/sctputil.h>
   41 #include <netinet/sctp_output.h>
   42 #include <netinet/sctp_bsd_addr.h>
   43 #include <netinet/sctp_uio.h>
   44 #include <netinet/sctputil.h>
   45 #include <netinet/sctp_timer.h>
   46 #include <netinet/sctp_asconf.h>
   47 #include <netinet/sctp_sysctl.h>
   48 #include <netinet/sctp_indata.h>
   49 #include <sys/unistd.h>
   50 
   51 
   52 /* Declare all of our malloc named types */
   53 
   54 /* Note to Michael/Peter for mac-os,
   55  * I think mac has this too since I
   56  * do see the M_PCB type, so I
   57  * will also put in the mac file the
   58  * MALLOC_DECLARE. If this does not
   59  * work for mac uncomment the defines for
   60  * the strings that we use in Panda, I put
   61  * them in comments in the mac-os file.
   62  */
   63 MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor");
   64 MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array");
   65 MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array");
   66 MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address");
   67 MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator");
   68 MALLOC_DEFINE(SCTP_M_AUTH_CL, "sctp_atcl", "sctp auth chunklist");
   69 MALLOC_DEFINE(SCTP_M_AUTH_KY, "sctp_atky", "sctp auth key");
   70 MALLOC_DEFINE(SCTP_M_AUTH_HL, "sctp_athm", "sctp auth hmac list");
   71 MALLOC_DEFINE(SCTP_M_AUTH_IF, "sctp_athi", "sctp auth info");
   72 MALLOC_DEFINE(SCTP_M_STRESET, "sctp_stre", "sctp stream reset");
   73 MALLOC_DEFINE(SCTP_M_CMSG, "sctp_cmsg", "sctp CMSG buffer");
   74 MALLOC_DEFINE(SCTP_M_COPYAL, "sctp_cpal", "sctp copy all");
   75 MALLOC_DEFINE(SCTP_M_VRF, "sctp_vrf", "sctp vrf struct");
   76 MALLOC_DEFINE(SCTP_M_IFA, "sctp_ifa", "sctp ifa struct");
   77 MALLOC_DEFINE(SCTP_M_IFN, "sctp_ifn", "sctp ifn struct");
   78 MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block");
   79 MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list");
   80 MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control");
   81 MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option");
   82 
   83 
   84 #if defined(SCTP_USE_THREAD_BASED_ITERATOR)
   85 void
   86 sctp_wakeup_iterator(void)
   87 {
   88         wakeup(&sctppcbinfo.iterator_running);
   89 }
   90 
   91 static void
   92 sctp_iterator_thread(void *v)
   93 {
   94         SCTP_IPI_ITERATOR_WQ_LOCK();
   95         sctppcbinfo.iterator_running = 0;
   96         while (1) {
   97                 msleep(&sctppcbinfo.iterator_running,
   98                     &sctppcbinfo.ipi_iterator_wq_mtx,
   99                     0, "waiting_for_work", 0);
  100                 sctp_iterator_worker();
  101         }
  102 }
  103 
  104 void
  105 sctp_startup_iterator(void)
  106 {
  107         int ret;
  108 
  109         ret = kthread_create(sctp_iterator_thread,
  110             (void *)NULL,
  111             &sctppcbinfo.thread_proc,
  112             RFPROC,
  113             SCTP_KTHREAD_PAGES,
  114             SCTP_KTRHEAD_NAME);
  115 }
  116 
  117 #endif
  118 
  119 
  120 void
  121 sctp_gather_internal_ifa_flags(struct sctp_ifa *ifa)
  122 {
  123         struct in6_ifaddr *ifa6;
  124 
  125         ifa6 = (struct in6_ifaddr *)ifa->ifa;
  126         ifa->flags = ifa6->ia6_flags;
  127         if (!ip6_use_deprecated) {
  128                 if (ifa->flags &
  129                     IN6_IFF_DEPRECATED) {
  130                         ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
  131                 } else {
  132                         ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
  133                 }
  134         } else {
  135                 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
  136         }
  137         if (ifa->flags &
  138             (IN6_IFF_DETACHED |
  139             IN6_IFF_ANYCAST |
  140             IN6_IFF_NOTREADY)) {
  141                 ifa->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE;
  142         } else {
  143                 ifa->localifa_flags &= ~SCTP_ADDR_IFA_UNUSEABLE;
  144         }
  145 }
  146 
  147 
  148 
  149 static uint32_t
  150 sctp_is_desired_interface_type(struct ifaddr *ifa)
  151 {
  152         int result;
  153 
  154         /* check the interface type to see if it's one we care about */
  155         switch (ifa->ifa_ifp->if_type) {
  156         case IFT_ETHER:
  157         case IFT_ISO88023:
  158         case IFT_ISO88024:
  159         case IFT_ISO88025:
  160         case IFT_ISO88026:
  161         case IFT_STARLAN:
  162         case IFT_P10:
  163         case IFT_P80:
  164         case IFT_HY:
  165         case IFT_FDDI:
  166         case IFT_XETHER:
  167         case IFT_ISDNBASIC:
  168         case IFT_ISDNPRIMARY:
  169         case IFT_PTPSERIAL:
  170         case IFT_OTHER:
  171         case IFT_PPP:
  172         case IFT_LOOP:
  173         case IFT_SLIP:
  174         case IFT_IP:
  175         case IFT_IPOVERCDLC:
  176         case IFT_IPOVERCLAW:
  177         case IFT_VIRTUALIPADDRESS:
  178                 result = 1;
  179                 break;
  180         default:
  181                 result = 0;
  182         }
  183 
  184         return (result);
  185 }
  186 
  187 static void
  188 sctp_init_ifns_for_vrf(int vrfid)
  189 {
  190         /*
  191          * Here we must apply ANY locks needed by the IFN we access and also
  192          * make sure we lock any IFA that exists as we float through the
  193          * list of IFA's
  194          */
  195         struct ifnet *ifn;
  196         struct ifaddr *ifa;
  197         struct in6_ifaddr *ifa6;
  198         struct sctp_ifa *sctp_ifa;
  199         uint32_t ifa_flags;
  200 
  201         TAILQ_FOREACH(ifn, &ifnet, if_list) {
  202                 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
  203                         if (ifa->ifa_addr == NULL) {
  204                                 continue;
  205                         }
  206                         if ((ifa->ifa_addr->sa_family != AF_INET) &&
  207                             (ifa->ifa_addr->sa_family != AF_INET6)
  208                             ) {
  209                                 /* non inet/inet6 skip */
  210                                 continue;
  211                         }
  212                         if (ifa->ifa_addr->sa_family == AF_INET6) {
  213                                 ifa6 = (struct in6_ifaddr *)ifa;
  214                                 ifa_flags = ifa6->ia6_flags;
  215                                 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
  216                                         /* skip unspecifed addresses */
  217                                         continue;
  218                                 }
  219                         } else if (ifa->ifa_addr->sa_family == AF_INET) {
  220                                 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
  221                                         continue;
  222                                 }
  223                         }
  224                         if (sctp_is_desired_interface_type(ifa) == 0) {
  225                                 /* non desired type */
  226                                 continue;
  227                         }
  228                         if ((ifa->ifa_addr->sa_family == AF_INET6) ||
  229                             (ifa->ifa_addr->sa_family == AF_INET)) {
  230                                 if (ifa->ifa_addr->sa_family == AF_INET6) {
  231                                         ifa6 = (struct in6_ifaddr *)ifa;
  232                                         ifa_flags = ifa6->ia6_flags;
  233                                 } else {
  234                                         ifa_flags = 0;
  235                                 }
  236                                 sctp_ifa = sctp_add_addr_to_vrf(vrfid,
  237                                     (void *)ifn,
  238                                     ifn->if_index,
  239                                     ifn->if_type,
  240                                     ifn->if_xname,
  241                                     (void *)ifa,
  242                                     ifa->ifa_addr,
  243                                     ifa_flags, 0
  244                                     );
  245                                 if (sctp_ifa) {
  246                                         sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
  247                                 }
  248                         }
  249                 }
  250         }
  251 }
  252 
  253 
  254 void
  255 sctp_init_vrf_list(int vrfid)
  256 {
  257         if (vrfid > SCTP_MAX_VRF_ID)
  258                 /* can't do that */
  259                 return;
  260 
  261         /* Don't care about return here */
  262         (void)sctp_allocate_vrf(vrfid);
  263 
  264         /*
  265          * Now we need to build all the ifn's for this vrf and there
  266          * addresses
  267          */
  268         sctp_init_ifns_for_vrf(vrfid);
  269 }
  270 
  271 static uint8_t first_time = 0;
  272 
  273 
  274 void
  275 sctp_addr_change(struct ifaddr *ifa, int cmd)
  276 {
  277         struct sctp_ifa *ifap = NULL;
  278         uint32_t ifa_flags = 0;
  279         struct in6_ifaddr *ifa6;
  280 
  281         /*
  282          * BSD only has one VRF, if this changes we will need to hook in the
  283          * right things here to get the id to pass to the address managment
  284          * routine.
  285          */
  286         if (first_time == 0) {
  287                 /* Special test to see if my ::1 will showup with this */
  288                 first_time = 1;
  289                 sctp_init_ifns_for_vrf(SCTP_DEFAULT_VRFID);
  290         }
  291         if ((cmd != RTM_ADD) && (cmd != RTM_DELETE)) {
  292                 /* don't know what to do with this */
  293                 return;
  294         }
  295         if (ifa->ifa_addr == NULL) {
  296                 return;
  297         }
  298         if ((ifa->ifa_addr->sa_family != AF_INET) &&
  299             (ifa->ifa_addr->sa_family != AF_INET6)
  300             ) {
  301                 /* non inet/inet6 skip */
  302                 return;
  303         }
  304         if (ifa->ifa_addr->sa_family == AF_INET6) {
  305                 ifa6 = (struct in6_ifaddr *)ifa;
  306                 ifa_flags = ifa6->ia6_flags;
  307                 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) {
  308                         /* skip unspecifed addresses */
  309                         return;
  310                 }
  311         } else if (ifa->ifa_addr->sa_family == AF_INET) {
  312                 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) {
  313                         return;
  314                 }
  315         }
  316         if (sctp_is_desired_interface_type(ifa) == 0) {
  317                 /* non desired type */
  318                 return;
  319         }
  320         if (cmd == RTM_ADD) {
  321                 ifap = sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, (void *)ifa->ifa_ifp,
  322                     ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type,
  323                     ifa->ifa_ifp->if_xname,
  324                     (void *)ifa, ifa->ifa_addr, ifa_flags, 1);
  325         } else if (cmd == RTM_DELETE) {
  326 
  327                 sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr,
  328                     ifa->ifa_ifp->if_index,
  329                     ifa->ifa_ifp->if_xname
  330                     );
  331                 /*
  332                  * We don't bump refcount here so when it completes the
  333                  * final delete will happen.
  334                  */
  335         }
  336 }
  337 
  338 struct mbuf *
  339 sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
  340     int how, int allonebuf, int type)
  341 {
  342         struct mbuf *m = NULL;
  343 
  344         m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
  345         if (m == NULL) {
  346                 /* bad, no memory */
  347                 return (m);
  348         }
  349         if (allonebuf) {
  350                 int siz;
  351 
  352                 if (SCTP_BUF_IS_EXTENDED(m)) {
  353                         siz = SCTP_BUF_EXTEND_SIZE(m);
  354                 } else {
  355                         if (want_header)
  356                                 siz = MHLEN;
  357                         else
  358                                 siz = MLEN;
  359                 }
  360                 if (siz < space_needed) {
  361                         m_freem(m);
  362                         return (NULL);
  363                 }
  364         }
  365         if (SCTP_BUF_NEXT(m)) {
  366                 sctp_m_freem(SCTP_BUF_NEXT(m));
  367                 SCTP_BUF_NEXT(m) = NULL;
  368         }
  369 #ifdef SCTP_MBUF_LOGGING
  370         if (sctp_logging_level & SCTP_MBUF_LOGGING_ENABLE) {
  371                 if (SCTP_BUF_IS_EXTENDED(m)) {
  372                         sctp_log_mb(m, SCTP_MBUF_IALLOC);
  373                 }
  374         }
  375 #endif
  376         return (m);
  377 }
  378 
  379 
  380 #ifdef SCTP_PACKET_LOGGING
  381 
  382 int packet_log_writers = 0;
  383 int packet_log_end = 0;
  384 uint8_t packet_log_buffer[SCTP_PACKET_LOG_SIZE];
  385 
  386 
  387 void
  388 sctp_packet_log(struct mbuf *m, int length)
  389 {
  390         int *lenat, thisone;
  391         void *copyto;
  392         uint32_t *tick_tock;
  393         int total_len;
  394         int grabbed_lock = 0;
  395         int value, newval, thisend, thisbegin;
  396 
  397         /*
  398          * Buffer layout. -sizeof this entry (total_len) -previous end
  399          * (value) -ticks of log      (ticks) o -ip packet o -as logged -
  400          * where this started (thisbegin) x <--end points here
  401          */
  402         total_len = SCTP_SIZE32((length + (4 * sizeof(int))));
  403         /* Log a packet to the buffer. */
  404         if (total_len > SCTP_PACKET_LOG_SIZE) {
  405                 /* Can't log this packet I have not a buffer big enough */
  406                 return;
  407         }
  408         if (length < (SCTP_MIN_V4_OVERHEAD + sizeof(struct sctp_cookie_ack_chunk))) {
  409                 return;
  410         }
  411         atomic_add_int(&packet_log_writers, 1);
  412 try_again:
  413         if (packet_log_writers > SCTP_PKTLOG_WRITERS_NEED_LOCK) {
  414                 SCTP_IP_PKTLOG_LOCK();
  415                 grabbed_lock = 1;
  416 again_locked:
  417                 value = packet_log_end;
  418                 newval = packet_log_end + total_len;
  419                 if (newval >= SCTP_PACKET_LOG_SIZE) {
  420                         /* we wrapped */
  421                         thisbegin = 0;
  422                         thisend = total_len;
  423                 } else {
  424                         thisbegin = packet_log_end;
  425                         thisend = newval;
  426                 }
  427                 if (!(atomic_cmpset_int(&packet_log_end, value, thisend))) {
  428                         goto again_locked;
  429                 }
  430         } else {
  431                 value = packet_log_end;
  432                 newval = packet_log_end + total_len;
  433                 if (newval >= SCTP_PACKET_LOG_SIZE) {
  434                         /* we wrapped */
  435                         thisbegin = 0;
  436                         thisend = total_len;
  437                 } else {
  438                         thisbegin = packet_log_end;
  439                         thisend = newval;
  440                 }
  441                 if (!(atomic_cmpset_int(&packet_log_end, value, thisend))) {
  442                         goto try_again;
  443                 }
  444         }
  445         /* Sanity check */
  446         if (thisend >= SCTP_PACKET_LOG_SIZE) {
  447                 printf("Insanity stops a log thisbegin:%d thisend:%d writers:%d lock:%d end:%d\n",
  448                     thisbegin,
  449                     thisend,
  450                     packet_log_writers,
  451                     grabbed_lock,
  452                     packet_log_end);
  453                 packet_log_end = 0;
  454                 goto no_log;
  455 
  456         }
  457         lenat = (int *)&packet_log_buffer[thisbegin];
  458         *lenat = total_len;
  459         lenat++;
  460         *lenat = value;
  461         lenat++;
  462         tick_tock = (uint32_t *) lenat;
  463         lenat++;
  464         *tick_tock = sctp_get_tick_count();
  465         copyto = (void *)lenat;
  466         thisone = thisend - sizeof(int);
  467         lenat = (int *)&packet_log_buffer[thisone];
  468         *lenat = thisbegin;
  469         if (grabbed_lock) {
  470                 SCTP_IP_PKTLOG_UNLOCK();
  471                 grabbed_lock = 0;
  472         }
  473         m_copydata(m, 0, length, (caddr_t)copyto);
  474 no_log:
  475         if (grabbed_lock) {
  476                 SCTP_IP_PKTLOG_UNLOCK();
  477         }
  478         atomic_subtract_int(&packet_log_writers, 1);
  479 }
  480 
  481 
  482 int
  483 sctp_copy_out_packet_log(uint8_t * target, int length)
  484 {
  485         /*
  486          * We wind through the packet log starting at start copying up to
  487          * length bytes out. We return the number of bytes copied.
  488          */
  489         int tocopy, this_copy;
  490         int *lenat;
  491         int did_delay = 0;
  492 
  493         tocopy = length;
  494         if (length < (2 * sizeof(int))) {
  495                 /* not enough room */
  496                 return (0);
  497         }
  498         if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
  499                 atomic_add_int(&packet_log_writers, SCTP_PKTLOG_WRITERS_NEED_LOCK);
  500 again:
  501                 if ((did_delay == 0) && (packet_log_writers != SCTP_PKTLOG_WRITERS_NEED_LOCK)) {
  502                         /*
  503                          * we delay here for just a moment hoping the
  504                          * writer(s) that were present when we entered will
  505                          * have left and we only have locking ones that will
  506                          * contend with us for the lock. This does not
  507                          * assure 100% access, but its good enough for a
  508                          * logging facility like this.
  509                          */
  510                         did_delay = 1;
  511                         DELAY(10);
  512                         goto again;
  513                 }
  514         }
  515         SCTP_IP_PKTLOG_LOCK();
  516         lenat = (int *)target;
  517         *lenat = packet_log_end;
  518         lenat++;
  519         this_copy = min((length - sizeof(int)), SCTP_PACKET_LOG_SIZE);
  520         memcpy((void *)lenat, (void *)packet_log_buffer, this_copy);
  521         if (SCTP_PKTLOG_WRITERS_NEED_LOCK) {
  522                 atomic_subtract_int(&packet_log_writers,
  523                     SCTP_PKTLOG_WRITERS_NEED_LOCK);
  524         }
  525         SCTP_IP_PKTLOG_UNLOCK();
  526         return (this_copy + sizeof(int));
  527 }
  528 
  529 #endif

Cache object: a0d769e7bdb99494e503354a3b6cc18d


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