示例#1
0
static void
mpls_forward(struct mbuf *m)
{
	struct sockaddr_mpls *smpls;
	struct mpls *mpls;
	struct route *cache_rt = &mplsforward_rt[mycpuid];
	mpls_label_t label;
	struct ifnet *ifp;
	struct sockaddr *dst;
	int error;

	KASSERT(m->m_len >= sizeof(struct mpls),
	    ("mpls_forward: mpls header not in one mbuf"));

	mpls = mtod(m, struct mpls *);
	label = MPLS_LABEL(ntohl(mpls->mpls_shim));

	smpls = (struct sockaddr_mpls *) &cache_rt->ro_dst;
	if (cache_rt->ro_rt == NULL || smpls->smpls_label != label) {
		if (cache_rt->ro_rt != NULL) {
			RTFREE(cache_rt->ro_rt);
			cache_rt->ro_rt = NULL;
		}
		smpls->smpls_family = AF_MPLS;
		smpls->smpls_len = sizeof(struct sockaddr_mpls);
		smpls->smpls_label = htonl(label);
		rtalloc(cache_rt);
		if (cache_rt->ro_rt == NULL) {
			/* route not found */
			return;
		}
	}

	ifp = cache_rt->ro_rt->rt_ifp;
	dst = cache_rt->ro_rt->rt_gateway;
	error = mpls_output(m, cache_rt->ro_rt);
	if (error)
		goto bad;
	error = (*ifp->if_output)(ifp, m, dst, cache_rt->ro_rt);
	if (error)
		goto bad;
	mplsstat.mplss_forwarded++;

	return;
bad:
	m_freem(m);
}
示例#2
0
void
mpls_hashfn(struct mbuf **mp, int hoff)
{
	struct mbuf *m = *mp;
	struct mpls *mpls;
	mpls_label_t label;
	struct ifnet *ifp;

	mpls_lengthcheck(mp, hoff);
	if ((m = *mp) == NULL)
		return;

	mpls = mtodoff(m, struct mpls *, hoff);

	label = MPLS_LABEL(ntohl(mpls->mpls_shim));
	ifp = m->m_pkthdr.rcvif;
	m->m_pkthdr.hash = MPLSP_MPORT_HASH(label, ifp->if_index);
	m->m_flags |= M_HASH;
}
示例#3
0
文件: echo.c 项目: millken/zhuxianB30
s32 mpls_echo_input(struct sk_buff * skb)
{
    s32 err = 0;
    s32 temp = 0;
    u32 saddr = 0;
    struct timeval tv;
    mpls_echo_hdr * echo;
    struct ethhdr * eth ;
    struct fib_mg_res res ;
    struct iphdr *iph = skb->nh.iph;
    struct udphdr * udph = skb->h.uh;
    
    echo = (mpls_echo_hdr *)(skb->data + sizeof(struct udphdr));
    skb_push(skb, iph->ihl * 4);
    err = fib_mg_lookup(if_dev_vrf(skb->dev)->vrf_id, iph->saddr, 32, &res);   
    if (err)
    {
        printk("mpls_echo_input -fib_mg_lookup drop.\n");
        goto drop;
    }
    
    temp = iph->daddr;
    iph->daddr = iph->saddr;
    if (res.dev)
    {
        iph->saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK);
    }
    else
    {
        iph->saddr = temp;
    }
    iph->ttl = 255;
    iph->check = 0;
    iph->check = ip_fast_csum(iph, iph->ihl);

    echo->type = MPLS_ECHO_REPLY;
    do_gettimeofday(&tv);
    echo->t_rcvd[0] = htonl(tv.tv_sec+JAN_1970);
    echo->t_rcvd[1] = NTPFRAC(tv.tv_usec);

    temp = udph->source;
    udph->source = udph->dest;
    udph->dest = temp;
    
    if (MPLS_MODE_DO_NOT_REPLY == echo->mode)
    {
        printk("mpls_echo_input -not reply mode drop.\n");
        goto drop;
    }
    
    if (MPLS_MODE_IPX_UDP_ALERT == echo->mode)
    {
        //Push router alert to ip option.
    }

    skb->protocol = htons(ETH_P_IP);
    if (FIB_MG_TYPE_FTN_BASIC == res.type)
    {
        if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel))
        {
            skb->protocol = htons(ETH_P_MPLS_UC) ;
            skb_push_label(skb, 128, res.glabel, 1);
        }

        if (2 == res.count)
        {
            if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2))
            {
                skb->protocol = htons(ETH_P_MPLS_UC) ;
                skb_push_label(skb, 128, res.glabel2, 0);
            }
        }
    }
    else
    {
        skb->protocol = htons(ETH_P_MPLS_UC) ;
        skb_push_label(skb, 128, res.label, 1);
        
        if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel))
        {
            skb_push_label(skb, 128, res.glabel, 0);
        }

        if (3 == res.count)
        {
            if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2))
            {
                skb->protocol = htons(ETH_P_MPLS_UC) ;
                skb_push_label(skb, 128, res.glabel2, 0);
            }
        }
    }

    if (MPLS_MODE_CTRL_CHANNEL == echo->mode)
    {
        skb_push_label(skb, 128, 1, 0);
    }

    skb->nh.raw = skb->data;
    
    skb->dev = res.dev;

    if (!res.neigh)
    {
        res.neigh = __neigh_arp_lookup(&arp_tbl, &res.nexthop, NULL, res.dev, NEIGHBOUR_CREAT);
    }
    
    read_lock_bh(&res.neigh->lock);
    
    if (!(res.neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE)))
    {
        saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK);
    
        arp_send(ARPOP_REQUEST, ETH_P_ARP, res.nexthop, res.dev, saddr,
           res.neigh->ha, res.dev->dev_addr, NULL);
        read_unlock_bh(&res.neigh->lock);
        printk("mpls_echo_input -neigh invalid drop.\n");
        goto drop;
    }

    eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
    eth->h_proto = (ETH_P_802_3 != skb->protocol) ? htons(skb->protocol) : htons(skb->len);
    memcpy(eth->h_source, res.dev->dev_addr, res.dev->addr_len);
    memcpy(eth->h_dest, res.neigh->ha, res.dev->addr_len);
    skb->mac.raw = skb->data ;
    skb->mac_len = ETH_HLEN; 

    read_unlock_bh(&res.neigh->lock);
        
    neigh_release(res.neigh);
    dev_queue_xmit(skb);
    
    return 0;
drop:
    kfree_skb(skb);
    return -1;
}
示例#4
0
void
icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
{
	char *cp;
	const struct icmp *dp;
        const struct icmp_ext_t *ext_dp;
	const struct ip *ip;
	const char *str, *fmt;
	const struct ip *oip;
	const struct udphdr *ouh;
        const u_int8_t *obj_tptr;
        u_int32_t raw_label;
        const u_char *snapend_save;
	const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header;
	u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype;
	char buf[MAXHOSTNAMELEN + 100];

	dp = (struct icmp *)bp;
        ext_dp = (struct icmp_ext_t *)bp;
	ip = (struct ip *)bp2;
	str = buf;

	TCHECK(dp->icmp_code);
	switch (dp->icmp_type) {

	case ICMP_ECHO:
	case ICMP_ECHOREPLY:
		TCHECK(dp->icmp_seq);
		(void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u",
                               dp->icmp_type == ICMP_ECHO ?
                               "request" : "reply",
                               EXTRACT_16BITS(&dp->icmp_id),
                               EXTRACT_16BITS(&dp->icmp_seq));
		break;

	case ICMP_UNREACH:
		TCHECK(dp->icmp_ip.ip_dst);
		switch (dp->icmp_code) {

		case ICMP_UNREACH_PROTOCOL:
			TCHECK(dp->icmp_ip.ip_p);
			(void)snprintf(buf, sizeof(buf),
			    "%s protocol %d unreachable",
			    ipaddr_string(&dp->icmp_ip.ip_dst),
			    dp->icmp_ip.ip_p);
			break;

		case ICMP_UNREACH_PORT:
			TCHECK(dp->icmp_ip.ip_p);
			oip = &dp->icmp_ip;
			hlen = IP_HL(oip) * 4;
			ouh = (struct udphdr *)(((u_char *)oip) + hlen);
			TCHECK(ouh->uh_dport);
			dport = EXTRACT_16BITS(&ouh->uh_dport);
			switch (oip->ip_p) {

			case IPPROTO_TCP:
				(void)snprintf(buf, sizeof(buf),
					"%s tcp port %s unreachable",
					ipaddr_string(&oip->ip_dst),
					tcpport_string(dport));
				break;

			case IPPROTO_UDP:
				(void)snprintf(buf, sizeof(buf),
					"%s udp port %s unreachable",
					ipaddr_string(&oip->ip_dst),
					udpport_string(dport));
				break;

			default:
				(void)snprintf(buf, sizeof(buf),
					"%s protocol %d port %d unreachable",
					ipaddr_string(&oip->ip_dst),
					oip->ip_p, dport);
				break;
			}
			break;

		case ICMP_UNREACH_NEEDFRAG:
		    {
			register const struct mtu_discovery *mp;
			mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void;
			mtu = EXTRACT_16BITS(&mp->nexthopmtu);
			if (mtu) {
				(void)snprintf(buf, sizeof(buf),
				    "%s unreachable - need to frag (mtu %d)",
				    ipaddr_string(&dp->icmp_ip.ip_dst), mtu);
			} else {
				(void)snprintf(buf, sizeof(buf),
				    "%s unreachable - need to frag",
				    ipaddr_string(&dp->icmp_ip.ip_dst));
			}
		    }
			break;

		default:
			fmt = tok2str(unreach2str, "#%d %%s unreachable",
			    dp->icmp_code);
			(void)snprintf(buf, sizeof(buf), fmt,
			    ipaddr_string(&dp->icmp_ip.ip_dst));
			break;
		}
		break;

	case ICMP_REDIRECT:
		TCHECK(dp->icmp_ip.ip_dst);
		fmt = tok2str(type2str, "redirect-#%d %%s to net %%s",
		    dp->icmp_code);
		(void)snprintf(buf, sizeof(buf), fmt,
		    ipaddr_string(&dp->icmp_ip.ip_dst),
		    ipaddr_string(&dp->icmp_gwaddr));
		break;

	case ICMP_ROUTERADVERT:
	    {
		register const struct ih_rdiscovery *ihp;
		register const struct id_rdiscovery *idp;
		u_int lifetime, num, size;

		(void)snprintf(buf, sizeof(buf), "router advertisement");
		cp = buf + strlen(buf);

		ihp = (struct ih_rdiscovery *)&dp->icmp_void;
		TCHECK(*ihp);
		(void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf));
		cp = buf + strlen(buf);
		lifetime = EXTRACT_16BITS(&ihp->ird_lifetime);
		if (lifetime < 60) {
			(void)snprintf(cp, sizeof(buf) - (cp - buf), "%u",
			    lifetime);
		} else if (lifetime < 60 * 60) {
			(void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u",
			    lifetime / 60, lifetime % 60);
		} else {
			(void)snprintf(cp, sizeof(buf) - (cp - buf),
			    "%u:%02u:%02u",
			    lifetime / 3600,
			    (lifetime % 3600) / 60,
			    lifetime % 60);
		}
		cp = buf + strlen(buf);

		num = ihp->ird_addrnum;
		(void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num);
		cp = buf + strlen(buf);

		size = ihp->ird_addrsiz;
		if (size != 2) {
			(void)snprintf(cp, sizeof(buf) - (cp - buf),
			    " [size %d]", size);
			break;
		}
		idp = (struct id_rdiscovery *)&dp->icmp_data;
		while (num-- > 0) {
			TCHECK(*idp);
			(void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}",
			    ipaddr_string(&idp->ird_addr),
			    EXTRACT_32BITS(&idp->ird_pref));
			cp = buf + strlen(buf);
			++idp;
		}
	    }
		break;

	case ICMP_TIMXCEED:
		TCHECK(dp->icmp_ip.ip_dst);
		switch (dp->icmp_code) {

		case ICMP_TIMXCEED_INTRANS:
			str = "time exceeded in-transit";
			break;

		case ICMP_TIMXCEED_REASS:
			str = "ip reassembly time exceeded";
			break;

		default:
			(void)snprintf(buf, sizeof(buf), "time exceeded-#%d",
			    dp->icmp_code);
			break;
		}
		break;

	case ICMP_PARAMPROB:
		if (dp->icmp_code)
			(void)snprintf(buf, sizeof(buf),
			    "parameter problem - code %d", dp->icmp_code);
		else {
			TCHECK(dp->icmp_pptr);
			(void)snprintf(buf, sizeof(buf),
			    "parameter problem - octet %d", dp->icmp_pptr);
		}
		break;

	case ICMP_MASKREPLY:
		TCHECK(dp->icmp_mask);
		(void)snprintf(buf, sizeof(buf), "address mask is 0x%08x",
		    EXTRACT_32BITS(&dp->icmp_mask));
		break;

	case ICMP_TSTAMP:
		TCHECK(dp->icmp_seq);
		(void)snprintf(buf, sizeof(buf),
		    "time stamp query id %u seq %u",
		    EXTRACT_16BITS(&dp->icmp_id),
		    EXTRACT_16BITS(&dp->icmp_seq));
		break;

	case ICMP_TSTAMPREPLY:
		TCHECK(dp->icmp_ttime);
		(void)snprintf(buf, sizeof(buf),
		    "time stamp reply id %u seq %u: org %s",
                               EXTRACT_16BITS(&dp->icmp_id),
                               EXTRACT_16BITS(&dp->icmp_seq),
                               icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime)));

                (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s",
                         icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime)));
                (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s",
                         icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime)));
                break;

	default:
		str = tok2str(icmp2str, "type-#%d", dp->icmp_type);
		break;
	}
	(void)printf("ICMP %s, length %u", str, plen);
	if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */
		u_int16_t sum, icmp_sum;
		if (TTEST2(*bp, plen)) {
			sum = in_cksum((u_short*)dp, plen, 0);
			if (sum != 0) {
				icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum);
				(void)printf(" (wrong icmp cksum %x (->%x)!)",
					     icmp_sum,
					     in_cksum_shouldbe(icmp_sum, sum));
			}
		}
	}

        /*
         * print the remnants of the IP packet.
         * save the snaplength as this may get overidden in the IP printer.
         */
	if (vflag >= 1 && !ICMP_INFOTYPE(dp->icmp_type)) {
		bp += 8;
		(void)printf("\n\t");
		ip = (struct ip *)bp;
		snaplen = snapend - bp;
                snapend_save = snapend;
		ip_print(gndo, bp, EXTRACT_16BITS(&ip->ip_len));
                snapend = snapend_save;
	}

        /*
         * Attempt to decode the MPLS extensions only for some ICMP types.
         */
        if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) {

            TCHECK(*ext_dp);

            /*
             * Check first if the mpls extension header shows a non-zero length.
             * If the length field is not set then silently verify the checksum
             * to check if an extension header is present. This is expedient,
             * however not all implementations set the length field proper.
             */
            if (!ext_dp->icmp_length &&
                in_cksum((const u_short *)&ext_dp->icmp_ext_version_res,
                         plen - ICMP_EXTD_MINLEN, 0)) {
                return;
            }

            printf("\n\tMPLS extension v%u",
                   ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)));
            
            /*
             * Sanity checking of the header.
             */
            if (ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) !=
                ICMP_MPLS_EXT_VERSION) {
                printf(" packet not supported");
                return;
            }

            hlen = plen - ICMP_EXTD_MINLEN;
            printf(", checksum 0x%04x (%scorrect), length %u",
                   EXTRACT_16BITS(ext_dp->icmp_ext_checksum),
                   in_cksum((const u_short *)&ext_dp->icmp_ext_version_res,
                            plen - ICMP_EXTD_MINLEN, 0) ? "in" : "",
                   hlen);

            hlen -= 4; /* subtract common header size */
            obj_tptr = (u_int8_t *)ext_dp->icmp_ext_data;

            while (hlen > sizeof(struct icmp_mpls_ext_object_header_t)) {

                icmp_mpls_ext_object_header = (struct icmp_mpls_ext_object_header_t *)obj_tptr;
                TCHECK(*icmp_mpls_ext_object_header);
                obj_tlen = EXTRACT_16BITS(icmp_mpls_ext_object_header->length);
                obj_class_num = icmp_mpls_ext_object_header->class_num;
                obj_ctype = icmp_mpls_ext_object_header->ctype;
                obj_tptr += sizeof(struct icmp_mpls_ext_object_header_t);

                printf("\n\t  %s Object (%u), Class-Type: %u, length %u",
                       tok2str(icmp_mpls_ext_obj_values,"unknown",obj_class_num),
                       obj_class_num,
                       obj_ctype,
                       obj_tlen);

                hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */

                /* infinite loop protection */                
                if ((obj_class_num == 0) ||
                    (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) {
                    return;
                }
                obj_tlen-=sizeof(struct icmp_mpls_ext_object_header_t);

                switch (obj_class_num) {
                case 1:
                    switch(obj_ctype) {
                    case 1:
                        TCHECK2(*obj_tptr, 4);
                        raw_label = EXTRACT_32BITS(obj_tptr);
                        printf("\n\t    label %u, exp %u", MPLS_LABEL(raw_label), MPLS_EXP(raw_label));
                        if (MPLS_STACK(raw_label))
                            printf(", [S]");
                        printf(", ttl %u", MPLS_TTL(raw_label));
                        break;
                    default:
                        print_unknown_data(obj_tptr, "\n\t    ", obj_tlen);
                    }
                    break;

               /*
                *  FIXME those are the defined objects that lack a decoder
                *  you are welcome to contribute code ;-)
                */
                case 2:
                default:
                    print_unknown_data(obj_tptr, "\n\t    ", obj_tlen);
                    break;
                }
                if (hlen < obj_tlen)
                    break;
                hlen -= obj_tlen;
                obj_tptr += obj_tlen;
            }
        }

	return;
trunc:
	fputs("[|icmp]", stdout);
}
/*
 * RFC3032: MPLS label stack encoding
 */
void
mpls_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	const u_char *p;
	uint32_t label_entry;
	uint16_t label_stack_depth = 0;
	enum mpls_packet_type pt = PT_UNKNOWN;

	p = bp;
	ND_PRINT((ndo, "MPLS"));
	do {
		ND_TCHECK2(*p, sizeof(label_entry));
		label_entry = EXTRACT_32BITS(p);
		ND_PRINT((ndo, "%s(label %u",
		       (label_stack_depth && ndo->ndo_vflag) ? "\n\t" : " ",
       		       MPLS_LABEL(label_entry)));
		label_stack_depth++;
		if (ndo->ndo_vflag &&
		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
			ND_PRINT((ndo, " (%s)", mpls_labelname[MPLS_LABEL(label_entry)]));
		ND_PRINT((ndo, ", exp %u", MPLS_EXP(label_entry)));
		if (MPLS_STACK(label_entry))
			ND_PRINT((ndo, ", [S]"));
		ND_PRINT((ndo, ", ttl %u)", MPLS_TTL(label_entry)));

		p += sizeof(label_entry);
	} while (!MPLS_STACK(label_entry));

	/*
	 * Try to figure out the packet type.
	 */
	switch (MPLS_LABEL(label_entry)) {

	case 0:	/* IPv4 explicit NULL label */
	case 3:	/* IPv4 implicit NULL label */
		pt = PT_IPV4;
		break;

	case 2:	/* IPv6 explicit NULL label */
		pt = PT_IPV6;
		break;

	default:
		/*
		 * Generally there's no indication of protocol in MPLS label
		 * encoding.
		 *
		 * However, draft-hsmit-isis-aal5mux-00.txt describes a
		 * technique for encapsulating IS-IS and IP traffic on the
		 * same ATM virtual circuit; you look at the first payload
		 * byte to determine the network layer protocol, based on
		 * the fact that
		 *
		 *	1) the first byte of an IP header is 0x45-0x4f
		 *	   for IPv4 and 0x60-0x6f for IPv6;
		 *
		 *	2) the first byte of an OSI CLNP packet is 0x81,
		 *	   the first byte of an OSI ES-IS packet is 0x82,
		 *	   and the first byte of an OSI IS-IS packet is
		 *	   0x83;
		 *
		 * so the network layer protocol can be inferred from the
		 * first byte of the packet, if the protocol is one of the
		 * ones listed above.
		 *
		 * Cisco sends control-plane traffic MPLS-encapsulated in
		 * this fashion.
		 */
		switch(*p) {

		case 0x45:
		case 0x46:
		case 0x47:
		case 0x48:
		case 0x49:
		case 0x4a:
		case 0x4b:
		case 0x4c:
		case 0x4d:
		case 0x4e:
		case 0x4f:
			pt = PT_IPV4;
			break;

		case 0x60:
		case 0x61:
		case 0x62:
		case 0x63:
		case 0x64:
		case 0x65:
		case 0x66:
		case 0x67:
		case 0x68:
		case 0x69:
		case 0x6a:
		case 0x6b:
		case 0x6c:
		case 0x6d:
		case 0x6e:
		case 0x6f:
			pt = PT_IPV6;
			break;

		case 0x81:
		case 0x82:
		case 0x83:
			pt = PT_OSI;
			break;

		default:
			/* ok bail out - we did not figure out what it is*/
			break;
		}
	}

	/*
	 * Print the payload.
	 */
	if (pt == PT_UNKNOWN) {
		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, length - (p - bp));
		return;
	}
	ND_PRINT((ndo, ndo->ndo_vflag ? "\n\t" : " "));
	switch (pt) {

	case PT_IPV4:
		ip_print(ndo, p, length - (p - bp));
		break;

	case PT_IPV6:
		ip6_print(ndo, p, length - (p - bp));
		break;

	case PT_OSI:
		isoclns_print(ndo, p, length - (p - bp), length - (p - bp));
		break;

	default:
		break;
	}
	return;

trunc:
	ND_PRINT((ndo, "[|MPLS]"));
}
示例#6
0
/*
 * RFC3032: MPLS label stack encoding
 */
void
mpls_print(const u_char *bp, u_int length)
{
	const u_char *p;
	u_int32_t label_entry;
        u_int16_t label_stack_depth = 0;

	p = bp;
	printf("MPLS");
	do {
		TCHECK2(*p, sizeof(label_entry));
		label_entry = EXTRACT_32BITS(p);
		printf("%s(label %u",
                       label_stack_depth ? "\n\t" : " ",
                       MPLS_LABEL(label_entry));
                label_stack_depth++;
		if (vflag &&
		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
			printf(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
		printf(", exp %u", MPLS_EXP(label_entry));
		if (MPLS_STACK(label_entry))
			printf(", [S]");
		printf(", ttl %u)", MPLS_TTL(label_entry));

		p += sizeof(label_entry);
	} while (!MPLS_STACK(label_entry));

	switch (MPLS_LABEL(label_entry)) {
	case 0:	/* IPv4 explicit NULL label */
        case 3:	/* IPv4 implicit NULL label */
                if (vflag>0) {
                        printf("\n\t");
                        ip_print(gndo, p, length - (p - bp));
                }
                else printf(", IP, length: %u",length);
		break;
#ifdef INET6
	case 2:	/* IPv6 explicit NULL label */
                if (vflag>0) {
                        printf("\n\t");
                        ip6_print(p, length - (p - bp));
                }
                else printf(", IPv6, length: %u",length);
		break;
#endif
	default:
		/*
		 * Generally there's no indication of protocol in MPLS label
		 * encoding, however draft-hsmit-isis-aal5mux-00.txt describes
                 * a technique that looks at the first payload byte if the BOS (bottom of stack)
                 * bit is set and tries to determine the network layer protocol
                 * 0x45-0x4f is IPv4
                 * 0x60-0x6f is IPv6
                 * 0x81-0x83 is OSI (CLNP,ES-IS,IS-IS)
                 * this technique is sometimes known as NULL encapsulation
                 * and decoding is particularly useful for control-plane traffic [BGP]
                 * which cisco by default sends MPLS encapsulated
		 */

                if (MPLS_STACK(label_entry)) { /* only do this if the stack bit is set */
                    switch(*p) {
                    case 0x45:
                    case 0x46:
                    case 0x47:
                    case 0x48:
                    case 0x49:
                    case 0x4a:
                    case 0x4b:
                    case 0x4c:
                    case 0x4d:
                    case 0x4e:
                    case 0x4f:
		        if (vflag>0) {
                            printf("\n\t");
                            ip_print(gndo, p, length - (p - bp));
			    }
                        else printf(", IP, length: %u",length);
                        break;
#ifdef INET6
                    case 0x60:
                    case 0x61:
                    case 0x62:
                    case 0x63:
                    case 0x64:
                    case 0x65:
                    case 0x66:
                    case 0x67:
                    case 0x68:
                    case 0x69:
                    case 0x6a:
                    case 0x6b:
                    case 0x6c:
                    case 0x6d:
                    case 0x6e:
                    case 0x6f:
		        if (vflag>0) {
                            printf("\n\t");
                            ip6_print(p, length - (p - bp));
                            }
			else printf(", IPv6, length: %u",length);
                        break;
#endif
                    case 0x81:
                    case 0x82:
                    case 0x83:
		        if (vflag>0) {
                            printf("\n\t");
                            isoclns_print(p, length - (p - bp), length - (p - bp));
			    }
			else printf(", OSI, length: %u",length);
                        break;
                    default:
                        /* ok bail out - we did not figure out what it is*/
                        break;
                    }
                }
                return;
	}

trunc:
	printf("[|MPLS]");
}
示例#7
0
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
    uint32_t len, PacketQueue *pq)
{
    uint32_t shim;
    int label;
    int event = 0;

    StatsIncr(tv, dtv->counter_mpls);

    do {
        if (len < MPLS_HEADER_LEN) {
            ENGINE_SET_INVALID_EVENT(p, MPLS_HEADER_TOO_SMALL);
            return TM_ECODE_FAILED;
        }
        memcpy(&shim, pkt, sizeof(shim));
        pkt += MPLS_HEADER_LEN;
        len -= MPLS_HEADER_LEN;
    } while (MPLS_BOTTOM(shim) == 0);

    label = MPLS_LABEL(shim);
    if (label == MPLS_LABEL_IPV4) {
        if (len > USHRT_MAX) {
            return TM_ECODE_FAILED;
        }
        return DecodeIPV4(tv, dtv, p, pkt, len, pq);
    }
    else if (label == MPLS_LABEL_ROUTER_ALERT) {
        /* Not valid at the bottom of the stack. */
        event = MPLS_BAD_LABEL_ROUTER_ALERT;
    }
    else if (label == MPLS_LABEL_IPV6) {
        if (len > USHRT_MAX) {
            return TM_ECODE_FAILED;
        }
        return DecodeIPV6(tv, dtv, p, pkt, len, pq);
    }
    else if (label == MPLS_LABEL_NULL) {
        /* Shouldn't appear on the wire. */
        event = MPLS_BAD_LABEL_IMPLICIT_NULL;
    }
    else if (label < MPLS_MAX_RESERVED_LABEL) {
        event = MPLS_BAD_LABEL_RESERVED;
    }

    if (event) {
        goto end;
    }

    // Make sure we still have enough data. While we only need 1 byte to test
    // for IPv4 and IPv4, we need for to check for ethernet.
    if (len < MPLS_PW_LEN) {
        ENGINE_SET_INVALID_EVENT(p, MPLS_PKT_TOO_SMALL);
        return TM_ECODE_FAILED;
    }

    /* Best guess at inner packet. */
    switch (pkt[0] >> 4) {
    case MPLS_PROTO_IPV4:
        if (len > USHRT_MAX) {
            return TM_ECODE_FAILED;
        }
        DecodeIPV4(tv, dtv, p, pkt, len, pq);
        break;
    case MPLS_PROTO_IPV6:
        if (len > USHRT_MAX) {
            return TM_ECODE_FAILED;
        }
        DecodeIPV6(tv, dtv, p, pkt, len, pq);
        break;
    case MPLS_PROTO_ETHERNET_PW:
        DecodeEthernet(tv, dtv, p, pkt + MPLS_PW_LEN, len - MPLS_PW_LEN,
            pq);
        break;
    default:
        ENGINE_SET_INVALID_EVENT(p, MPLS_UNKNOWN_PAYLOAD_TYPE);
        return TM_ECODE_OK;
    }

end:
    if (event) {
        ENGINE_SET_EVENT(p, event);
    }
    return TM_ECODE_OK;
}
示例#8
0
void
mpls_input(struct mbuf *m)
{
	struct mpls *mpls = NULL;
	mpls_label_t label;

	M_ASSERTPKTHDR(m);

	mplsstat.mplss_total++;

	/* length checks already performed at mpls_demux() */
	KASSERT(m->m_pkthdr.len >= sizeof(struct mpls),
	    ("mpls_input: mpls header too small"));
	
again:
	if (m->m_len < sizeof(struct mpls)) {
		m = m_pullup(m, sizeof(struct mpls));
		if (m == NULL) {
			mplsstat.mplss_toosmall++;
			return;
		}
	}

	mpls = mtod(m, struct mpls*);
	label = MPLS_LABEL(ntohl(mpls->mpls_shim));
	switch (label) {
	case 0:
		/* 
		 * Label 0: represents "IPv4 Explicit NULL Label".
		 */
		if (MPLS_STACK(ntohl(mpls->mpls_shim))) {
			/* Decapsulate the ip datagram from the mpls frame. */
			m_adj(m, sizeof(struct mpls));
			netisr_queue(NETISR_IP, m);
			return;
		}
		goto again; /* If not the bottom label, per RFC4182. */

	case 1:
		/*
		 * Label 1: represents "Router Alert Label" and is valid 
		 * anywhere except at the bottom of the stack.
		 */
		break;

	case 2:
		/* 
		 * Label 2: represents "IPv6 Explicit NULL Label".
		 */
		if (MPLS_STACK(ntohl(mpls->mpls_shim))) {
			/* Decapsulate the ip datagram from the mpls frame. */
			m_adj(m, sizeof(struct mpls));
			netisr_queue(NETISR_IPV6, m);
			return;
		}
		goto again; /* If not the bottom label, per RFC4182. */

	case 3:
		/*
		 * Label 3: represents the "Implicit NULL Label" and must not 
		 * appear on the wire.
		 */
		break;
	default:
		/*
		 * Labels 4 - 15: reserved, drop them.
		 */
		if (label <= 15) {
			mplsstat.mplss_reserved++;
			m_freem(m);
			return;
		}
		if (mplsforwarding) {
			mpls_forward(m);
			return;
		} else {
			mplsstat.mplss_cantforward++;
			m_freem(m);
			return;
		}
	}

	mplsstat.mplss_invalid++;
	m_freem(m);
}
示例#9
0
int DecodeMPLS(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt,
    uint16_t len, PacketQueue *pq)
{
    uint32_t shim;
    int label;
    int event = 0;

    StatsIncr(tv, dtv->counter_mpls);

    do {
        if (len < MPLS_HEADER_LEN) {
            ENGINE_SET_INVALID_EVENT(p, MPLS_HEADER_TOO_SMALL);
            return TM_ECODE_FAILED;
        }
        shim = *(uint32_t *)pkt;
        pkt += MPLS_HEADER_LEN;
        len -= MPLS_HEADER_LEN;
    } while (MPLS_BOTTOM(shim) == 0);

    label = MPLS_LABEL(shim);
    if (label == MPLS_LABEL_IPV4) {
        return DecodeIPV4(tv, dtv, p, pkt, len, pq);
    }
    else if (label == MPLS_LABEL_ROUTER_ALERT) {
        /* Not valid at the bottom of the stack. */
        event = MPLS_BAD_LABEL_ROUTER_ALERT;
    }
    else if (label == MPLS_LABEL_IPV6) {
        return DecodeIPV6(tv, dtv, p, pkt, len, pq);
    }
    else if (label == MPLS_LABEL_NULL) {
        /* Shouldn't appear on the wire. */
        event = MPLS_BAD_LABEL_IMPLICIT_NULL;
    }
    else if (label < MPLS_MAX_RESERVED_LABEL) {
        event = MPLS_BAD_LABEL_RESERVED;
    }

    if (event) {
        goto end;
    }

    /* Best guess at inner packet. */
    switch (pkt[0] >> 4) {
    case MPLS_PROTO_IPV4:
        DecodeIPV4(tv, dtv, p, pkt, len, pq);
        break;
    case MPLS_PROTO_IPV6:
        DecodeIPV6(tv, dtv, p, pkt, len, pq);
        break;
    case MPLS_PROTO_ETHERNET_PW:
        DecodeEthernet(tv, dtv, p, pkt + MPLS_PW_LEN, len - MPLS_PW_LEN,
            pq);
        break;
    default:
        ENGINE_SET_INVALID_EVENT(p, MPLS_UNKNOWN_PAYLOAD_TYPE);
        return TM_ECODE_OK;
    }

end:
    if (event) {
        ENGINE_SET_EVENT(p, event);
    }
    return TM_ECODE_OK;
}