LCOV - code coverage report
Current view: top level - netmpls - mpls_output.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 69 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: mpls_output.c,v 1.26 2015/12/02 08:47:00 claudio Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
       5             :  * Copyright (c) 2008 Michele Marchetto <michele@openbsd.org>
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : #include <sys/param.h>
      21             : #include <sys/mbuf.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/socket.h>
      24             : 
      25             : #include <net/if.h>
      26             : #include <net/if_var.h>
      27             : #include <net/route.h>
      28             : 
      29             : #include <netmpls/mpls.h>
      30             : 
      31             : #include <netinet/in.h>
      32             : #include <netinet/ip.h>
      33             : 
      34             : #ifdef INET6
      35             : #include <netinet/ip6.h>
      36             : #endif
      37             : 
      38             : #ifdef MPLS_DEBUG
      39             : #define MPLS_LABEL_GET(l)       ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET)
      40             : #endif
      41             : 
      42             : void            mpls_do_cksum(struct mbuf *);
      43             : u_int8_t        mpls_getttl(struct mbuf *, sa_family_t);
      44             : 
      45             : int
      46           0 : mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
      47             :     struct rtentry *rt)
      48             : {
      49             :         struct sockaddr_mpls    *smpls;
      50           0 :         struct sockaddr_mpls     sa_mpls;
      51             :         struct shim_hdr         *shim;
      52             :         struct rt_mpls          *rt_mpls;
      53             :         int                      error;
      54             :         u_int8_t                 ttl;
      55             : 
      56           0 :         if (rt == NULL || (dst->sa_family != AF_INET &&
      57           0 :             dst->sa_family != AF_INET6 && dst->sa_family != AF_MPLS)) {
      58           0 :                 if (!ISSET(ifp->if_xflags, IFXF_MPLS))
      59           0 :                         return (ifp->if_output(ifp, m, dst, rt));
      60             :                 else
      61           0 :                         return (ifp->if_ll_output(ifp, m, dst, rt));
      62             :         }
      63             : 
      64             :         /* need to calculate checksums now if necessary */
      65           0 :         mpls_do_cksum(m);
      66             : 
      67             :         /* initialize sockaddr_mpls */
      68           0 :         bzero(&sa_mpls, sizeof(sa_mpls));
      69             :         smpls = &sa_mpls;
      70           0 :         smpls->smpls_family = AF_MPLS;
      71           0 :         smpls->smpls_len = sizeof(*smpls);
      72             : 
      73           0 :         ttl = mpls_getttl(m, dst->sa_family);
      74             : 
      75           0 :         rt_mpls = (struct rt_mpls *)rt->rt_llinfo;
      76           0 :         if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) {
      77             :                 /* no MPLS information for this entry */
      78           0 :                 if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
      79             : #ifdef MPLS_DEBUG
      80             :                         printf("MPLS_DEBUG: interface not mpls enabled\n");
      81             : #endif
      82             :                         error = ENETUNREACH;
      83           0 :                         goto bad;
      84             :                 }
      85             : 
      86           0 :                 return (ifp->if_ll_output(ifp, m, dst, rt));
      87             :         }
      88             : 
      89             :         /* to be honest here only the push operation makes sense */
      90           0 :         switch (rt_mpls->mpls_operation) {
      91             :         case MPLS_OP_PUSH:
      92           0 :                 m = mpls_shim_push(m, rt_mpls);
      93           0 :                 break;
      94             :         case MPLS_OP_POP:
      95           0 :                 m = mpls_shim_pop(m);
      96           0 :                 break;
      97             :         case MPLS_OP_SWAP:
      98           0 :                 m = mpls_shim_swap(m, rt_mpls);
      99           0 :                 break;
     100             :         default:
     101             :                 error = EINVAL;
     102           0 :                 goto bad;
     103             :         }
     104             : 
     105           0 :         if (m == NULL) {
     106             :                 error = ENOBUFS;
     107           0 :                 goto bad;
     108             :         }
     109             : 
     110             :         /* refetch label */
     111           0 :         shim = mtod(m, struct shim_hdr *);
     112             :         /* mark first label with BOS flag */
     113           0 :         if (dst->sa_family != AF_MPLS)
     114           0 :                 shim->shim_label |= MPLS_BOS_MASK;
     115             : 
     116             :         /* write back TTL */
     117           0 :         shim->shim_label &= ~MPLS_TTL_MASK;
     118           0 :         shim->shim_label |= htonl(ttl);
     119             : 
     120             : #ifdef MPLS_DEBUG
     121             :         printf("MPLS: sending on %s outshim %x outlabel %d\n",
     122             :             ifp->if_xname, ntohl(shim->shim_label),
     123             :             MPLS_LABEL_GET(rt_mpls->mpls_label));
     124             : #endif
     125             : 
     126             :         /* Output iface is not MPLS-enabled */
     127           0 :         if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
     128             : #ifdef MPLS_DEBUG
     129             :                 printf("MPLS_DEBUG: interface not mpls enabled\n");
     130             : #endif
     131             :                 error = ENETUNREACH;
     132           0 :                 goto bad;
     133             :         }
     134             : 
     135             :         /* reset broadcast and multicast flags, this is a P2P tunnel */
     136           0 :         m->m_flags &= ~(M_BCAST | M_MCAST);
     137             : 
     138           0 :         smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK;
     139           0 :         error = ifp->if_ll_output(ifp, m, smplstosa(smpls), rt);
     140           0 :         return (error);
     141             : bad:
     142           0 :         m_freem(m);
     143           0 :         return (error);
     144           0 : }
     145             : 
     146             : void
     147           0 : mpls_do_cksum(struct mbuf *m)
     148             : {
     149             :         struct ip *ip;
     150             :         u_int16_t hlen;
     151             : 
     152           0 :         in_proto_cksum_out(m, NULL);
     153             : 
     154           0 :         if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT) {
     155           0 :                 ip = mtod(m, struct ip *);
     156           0 :                 hlen = ip->ip_hl << 2;
     157           0 :                 ip->ip_sum = in_cksum(m, hlen);
     158           0 :                 m->m_pkthdr.csum_flags &= ~M_IPV4_CSUM_OUT;
     159           0 :         }
     160           0 : }
     161             : 
     162             : u_int8_t
     163           0 : mpls_getttl(struct mbuf *m, sa_family_t af)
     164             : {
     165             :         struct shim_hdr *shim;
     166             :         struct ip *ip;
     167             : #ifdef INET6
     168             :         struct ip6_hdr *ip6hdr;
     169             : #endif
     170           0 :         u_int8_t ttl = mpls_defttl;
     171             : 
     172             :         /* If the AF is MPLS then inherit the TTL from the present label. */
     173           0 :         if (af == AF_MPLS) {
     174           0 :                 shim = mtod(m, struct shim_hdr *);
     175           0 :                 ttl = ntohl(shim->shim_label & MPLS_TTL_MASK);
     176           0 :                 return (ttl);
     177             :         }
     178             :         /* Else extract TTL from the encapsualted packet. */
     179           0 :         switch (*mtod(m, u_char *) >> 4) {
     180             :         case IPVERSION:
     181           0 :                 if (!mpls_mapttl_ip)
     182             :                         break;
     183           0 :                 if (m->m_len < sizeof(*ip))
     184             :                         break;                  /* impossible */
     185           0 :                 ip = mtod(m, struct ip *);
     186           0 :                 ttl = ip->ip_ttl;
     187           0 :                 break;
     188             : #ifdef INET6
     189             :         case IPV6_VERSION >> 4:
     190           0 :                 if (!mpls_mapttl_ip6)
     191             :                         break;
     192           0 :                 if (m->m_len < sizeof(struct ip6_hdr))
     193             :                         break;                  /* impossible */
     194           0 :                 ip6hdr = mtod(m, struct ip6_hdr *);
     195           0 :                 ttl = ip6hdr->ip6_hlim;
     196           0 :                 break;
     197             : #endif
     198             :         default:
     199             :                 break;
     200             :         }
     201           0 :         return (ttl);
     202           0 : }

Generated by: LCOV version 1.13