22 * entries here. The conn_recv* functions live here too (for now).
23 */
24
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ksynch.h>
28 #include <sys/ksocket.h>
29 #include <sys/kmem.h>
30 #include <sys/stream.h>
31 #include <sys/strsubr.h>
32 #include <sys/strsun.h>
33 #include <sys/sysmacros.h>
34 #include <sys/debug.h>
35 #include <sys/dtrace.h>
36 #include <sys/errno.h>
37 #include <sys/tihdr.h>
38 #include <netinet/in.h>
39 #include <netinet/udp.h>
40 #include <inet/ip.h>
41 #include <inet/ip6.h>
42 #include <inet/udp_impl.h>
43 #include <inet/tcp.h>
44
45 #include <inet/vxlnat_impl.h>
46
47 static boolean_t vxlnat_vxlan_input(ksocket_t, mblk_t *, size_t, int, void *);
48 static mblk_t *vxlnat_fixed_fixv4(mblk_t *mp, vxlnat_fixed_t *fixed,
49 boolean_t to_private);
50
51 /*
52 * Initialized to NULL, read/write protected by vxlnat_mutex.
53 * Receive functions shouldn't have to access this directly.
54 */
55 ksocket_t vxlnat_underlay;
56 ire_t *vxlnat_underlay_ire;
57
58 void
59 vxlnat_closesock(void)
60 {
61 ASSERT(MUTEX_HELD(&vxlnat_mutex));
332 remote->vxnrem_uaddr = underlay_src->sin6_addr;
333 }
334 /* Replace the vlan ID. Maintain network order... */
335 if (remote->vxnrem_vlan != vlan)
336 remote->vxnrem_vlan = vlan;
337 }
338 /*
339 * Else just continue and pray for better luck on another packet or
340 * on the return flight. It is IP, we can Just Drop It (TM)...
341 */
342
343 /* We're done with the remote entry now. */
344 VXNREM_REFRELE(remote);
345
346 /* Advance rptr to the inner IP header and proceed. */
347 mp->b_rptr = (uint8_t *)ipha;
348 return (mp);
349 }
350
351 /*
352 * Inspect the packet and find ports & protos (or ICMP types & codes)
353 * and see if we have an established NAT flow.
354 *
355 * XXX KEBE WONDERS if the transmission path will more closely resemble
356 * vxlnat_one_vxlan_fixed() because of ipha_ident issues or not...
357 *
358 * B_TRUE means the packet was handled, and we shouldn't continue processing
359 * (even if "was handled" means droppage).
360 */
361 static boolean_t
362 vxlnat_one_vxlan_flow(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
363 ip6_t *ip6h)
364 {
365 /* XXX KEBE SAYS FILL ME IN. */
366 /* For now... */
367 return (B_FALSE);
368 }
369
370 /*
371 * If we reach here, we need to find a NAT rule, and see if we can/should
372 * CREATE a new NAT flow, or whether or not we should drop, maybe even
373 * returning an ICMP message of some sort.
374 *
375 * B_TRUE means the packet was handled, and we shouldn't continue processing
376 * (even if "was handled" means droppage).
377 */
378 static boolean_t
379 vxlnat_one_vxlan_rule(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
380 ip6_t *ip6h)
381 {
382 vxlnat_rule_t *rule;
383
384 /* XXX handle IPv6 later */
385 if (ip6h != NULL)
386 return (B_FALSE);
387
388 ASSERT3P(ipha, !=, NULL);
389
390 mutex_enter(&vnet->vxnv_rule_lock);
391 rule = list_head(&vnet->vxnv_rules);
392
393 /*
394 * search for a match in the nat rules
395 * XXX investigate perf issues with with respect to list_t size
396 */
397 while (rule != NULL) {
398 ipaddr_t ipaddr;
399 uint32_t netmask = 0xffffffff;
400 uint8_t prefix = rule->vxnr_prefix - 96;
401
402 /* calculate the v4 netmask */
403 netmask <<= (32 - prefix);
404 netmask = htonl(netmask);
405
406 IN6_V4MAPPED_TO_IPADDR(&rule->vxnr_myaddr, ipaddr);
407 /* XXX ASSERT vlanid? */
408 if ((ipaddr & netmask) == (ipha->ipha_src & netmask)) {
409 VXNR_REFHOLD(rule);
410 break;
411 }
412
413 rule = list_next(&vnet->vxnv_rules, rule);
414 }
415
416 mutex_exit(&vnet->vxnv_rule_lock);
417
418 if (rule == NULL)
419 return (B_FALSE);
420
421 /* process packet */
422 /*
423 static vxlnat_flow_t *
424 vxlnat_new_flow(vxlnat_rule_t *rule, in6_addr_t *inner_src, in6_addr_t *dst,
425 uint32_t ports, uint8_t protocol)
426 */
427
428 return (B_FALSE);
429 }
430
431 /*
432 * See if the inbound VXLAN packet hits a 1-1/fixed mapping, and process if it
433 * does. B_TRUE means the packet was handled, and we shouldn't continue
434 * processing (even if "was handled" means droppage).
435 */
436 static boolean_t
437 vxlnat_one_vxlan_fixed(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
438 ip6_t *ip6h)
439 {
440 vxlnat_fixed_t *fixed, fsearch;
441 mblk_t *newmp;
442 ire_t *outbound_ire;
443 /* Use C99's initializers for fun & profit. */
444 ip_recv_attr_t iras = { IRAF_IS_IPV4 | IRAF_VERIFIED_SRC };
445
446 if (ipha != NULL) {
447 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src),
547 if (vxh->vxlan_flags != VXLAN_F_VDI_WIRE) {
548 DTRACE_PROBE1(vxlnat__in__drop__VDI, mblk_t *, mp);
549 freemsg(mp);
550 return;
551 }
552
553 /* Remember, we key off of what's on the wire. */
554 vnet = vxlnat_get_vnet(VXLAN_ID_WIRE32(vxh->vxlan_id), B_FALSE);
555 if (vnet == NULL) {
556 DTRACE_PROBE1(vxlnat__in__drop__vnetid, uint32_t,
557 VXLAN_ID_HTON(VXLAN_ID_WIRE32(vxh->vxlan_id)));
558 freemsg(mp);
559 return;
560 }
561
562 DTRACE_PROBE2(vxlnat__in__vnet, uint32_t,
563 VXLAN_ID_HTON(VXLAN_ID_WIRE32(vxh->vxlan_id)),
564 vxlnat_vnet_t, vnet);
565
566 /*
567 * Off-vxlan processing steps:
568 * 1.) Locate the ethernet header and check/update/add-into remotes.
569 * 2.) Search 1-1s, process if hit.
570 * 3.) Search flows, process if hit.
571 * 4.) Search rules, create new flow (or not) if hit.
572 * 5.) Drop the packets.
573 */
574
575 /* 1.) Locate the ethernet header and check/update/add-into remotes. */
576 mp->b_rptr += sizeof (*vxh);
577 while (MBLKL(mp) == 0) {
578 mblk_t *oldmp = mp;
579
580 mp = mp->b_cont;
581 freeb(oldmp);
582 }
583 mp = vxlnat_cache_remote(mp, underlay_src, vnet);
584 if (mp == NULL)
585 goto bail_no_free;
586
587 /* Let's cache the IP header here... */
588 ipha = (ipha_t *)mp->b_rptr;
589 switch (IPH_HDR_VERSION(ipha)) {
590 case IPV4_VERSION:
591 ip6h = NULL;
592 break;
|
22 * entries here. The conn_recv* functions live here too (for now).
23 */
24
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/ksynch.h>
28 #include <sys/ksocket.h>
29 #include <sys/kmem.h>
30 #include <sys/stream.h>
31 #include <sys/strsubr.h>
32 #include <sys/strsun.h>
33 #include <sys/sysmacros.h>
34 #include <sys/debug.h>
35 #include <sys/dtrace.h>
36 #include <sys/errno.h>
37 #include <sys/tihdr.h>
38 #include <netinet/in.h>
39 #include <netinet/udp.h>
40 #include <inet/ip.h>
41 #include <inet/ip6.h>
42 #include <inet/tcp_impl.h>
43 #include <inet/udp_impl.h>
44 #include <inet/tcp.h>
45
46 #include <inet/vxlnat_impl.h>
47
48 static boolean_t vxlnat_vxlan_input(ksocket_t, mblk_t *, size_t, int, void *);
49 static mblk_t *vxlnat_fixed_fixv4(mblk_t *mp, vxlnat_fixed_t *fixed,
50 boolean_t to_private);
51
52 /*
53 * Initialized to NULL, read/write protected by vxlnat_mutex.
54 * Receive functions shouldn't have to access this directly.
55 */
56 ksocket_t vxlnat_underlay;
57 ire_t *vxlnat_underlay_ire;
58
59 void
60 vxlnat_closesock(void)
61 {
62 ASSERT(MUTEX_HELD(&vxlnat_mutex));
333 remote->vxnrem_uaddr = underlay_src->sin6_addr;
334 }
335 /* Replace the vlan ID. Maintain network order... */
336 if (remote->vxnrem_vlan != vlan)
337 remote->vxnrem_vlan = vlan;
338 }
339 /*
340 * Else just continue and pray for better luck on another packet or
341 * on the return flight. It is IP, we can Just Drop It (TM)...
342 */
343
344 /* We're done with the remote entry now. */
345 VXNREM_REFRELE(remote);
346
347 /* Advance rptr to the inner IP header and proceed. */
348 mp->b_rptr = (uint8_t *)ipha;
349 return (mp);
350 }
351
352 /*
353 * Extract transport-level information to find a NAT flow.
354 * Consume mp and return B_FALSE if there's a problem. Fill in "ports"
355 * and "protocol" and return B_TRUE if there's not.
356 */
357 static boolean_t
358 vxlnat_grab_transport(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h, uint32_t *ports,
359 uint8_t *protocol, uint8_t **nexthdr_ptr)
360 {
361 uint8_t *nexthdr;
362
363 /* Punt on IPv6 for now... */
364 if (ip6h != NULL) {
365 freemsg(mp);
366 return (B_FALSE);
367 }
368
369 ASSERT(ipha != NULL);
370 *protocol = ipha->ipha_protocol;
371 nexthdr = ((uint8_t *)ipha + IPH_HDR_LENGTH(ipha));
372 *nexthdr_ptr = nexthdr; /* Get this out of the way now. */
373 if (nexthdr > mp->b_wptr) {
374 DTRACE_PROBE1(vxlnat__in__drop__trnexthdr, mblk_t *, mp);
375 freemsg(mp);
376 return (B_FALSE);
377 }
378 switch (*protocol) {
379 case IPPROTO_TCP: {
380 tcpha_t *tcph = (tcpha_t *)nexthdr;
381
382 if (nexthdr + sizeof (*tcph) > mp->b_wptr) {
383 DTRACE_PROBE1(vxlnat__in__drop__tcpnexthdr, mblk_t *,
384 mp);
385 freemsg(mp);
386 return (B_FALSE);
387 }
388 *ports = *((uint32_t *)tcph);
389 /* XXX KEBE SAYS - grab other metadata here NOW? */
390 break;
391 }
392 case IPPROTO_UDP: {
393 udpha_t *udph = (udpha_t *)nexthdr;
394
395 if (nexthdr + sizeof (*udph) > mp->b_wptr) {
396 DTRACE_PROBE1(vxlnat__in__drop__udpnexthdr, mblk_t *,
397 mp);
398 freemsg(mp);
399 return (B_FALSE);
400 }
401 *ports = *((uint32_t *)udph);
402 /*
403 * XXX KEBE SAYS - not as much as TCP, but grab other metadata
404 * here NOW?
405 */
406 break;
407 }
408 case IPPROTO_ICMP: {
409 icmph_t *icmph = (icmph_t *)nexthdr;
410
411 if (nexthdr + sizeof (*icmph) > mp->b_wptr) {
412 DTRACE_PROBE1(vxlnat__in__drop__icmpnexthdr, mblk_t *,
413 mp);
414 freemsg(mp);
415 return (B_FALSE);
416 }
417 /* XXX KEBE SAYS sort out ICMP header... */
418 switch (icmph->icmph_type) {
419 case ICMP_ECHO_REQUEST:
420 case ICMP_TIME_STAMP_REQUEST:
421 case ICMP_TIME_EXCEEDED:
422 case ICMP_INFO_REQUEST:
423 case ICMP_ADDRESS_MASK_REPLY:
424 /* All ones we can sorta cope with... */
425 break;
426 default:
427 DTRACE_PROBE2(vxlnat__in__drop__icmptype, int,
428 icmph->icmph_type, mblk_t *, mp);
429 freemsg(mp);
430 return (B_FALSE);
431 }
432 /* NOTE: as of now, will switch position depending on endian. */
433 *ports = icmph->icmph_echo_ident;
434 break;
435 }
436 default:
437 *ports = 0;
438 break;
439 }
440
441 return (B_TRUE);
442 }
443
444 /*
445 * This is the evaluate-packet vs. NAT flow state function.
446 * This function does NOT alter "mp".
447 */
448 static boolean_t
449 vxlnat_verify_natstate(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h,
450 vxlnat_flow_t *flow, uint8_t *nexthdr)
451 {
452 /* XXX KEBE SAYS FILL ME IN! */
453 return (B_FALSE);
454 }
455
456 /*
457 * Inspect the packet and find ports & protos (or ICMP types & codes)
458 * and see if we have an established NAT flow.
459 *
460 * XXX KEBE WONDERS if the transmission path will more closely resemble
461 * vxlnat_one_vxlan_fixed() because of ipha_ident issues or not...
462 *
463 * B_TRUE means the packet was handled, and we shouldn't continue processing
464 * (even if "was handled" means droppage).
465 */
466 static boolean_t
467 vxlnat_one_vxlan_flow(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
468 ip6_t *ip6h)
469 {
470 vxlnat_flow_t *flow, searcher;
471 uint8_t *nexthdr;
472
473 /*
474 * XXX KEBE WONDERS, should we return vxlnat_flow_t instead if we
475 * miss? That way, we only need to find the ports/protocol ONCE.
476 */
477
478 if (ip6h != NULL) {
479 /* Eventually, grab addresses for "searcher". */
480 return (B_FALSE); /* Bail on IPv6 for now... */
481 } else {
482 ASSERT(ipha != NULL);
483 searcher.vxnfl_isv4 = B_TRUE; /* Required? */
484 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src),
485 &searcher.vxnfl_src);
486 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_dst),
487 &searcher.vxnfl_dst);
488 }
489
490 if (!vxlnat_grab_transport(mp, ipha, ip6h, &searcher.vxnfl_ports,
491 &searcher.vxnfl_protocol, &nexthdr)) {
492 DTRACE_PROBE1(vxlnat__in__flowgrab, mblk_t *, mp);
493 freemsg(mp);
494 return (B_TRUE);
495 }
496
497
498 /*
499 * XXX KEBE SAYS Eventually put the rw&find in an IPv4-only block,
500 * because IPv6 (if we NAT it like IPv4) will have its own table/tree.
501 */
502 rw_enter(&vnet->vxnv_flowv4_lock, RW_READER);
503 flow = avl_find(&vnet->vxnv_flows_v4, &searcher, NULL);
504 if (flow != NULL)
505 VXNFL_REFHOLD(flow);
506 rw_exit(&vnet->vxnv_flowv4_lock);
507
508 if (flow == NULL)
509 return (B_FALSE); /* Let caller handle things. */
510
511 if (!vxlnat_verify_natstate(mp, ipha, ip6h, flow, nexthdr)) {
512 freemsg(mp); /* XXX KEBE SAYS FOR NOW... */
513 } else {
514 /* XXX KEBE SAYS PROCESS... */
515 }
516
517 VXNFL_REFRELE(flow);
518 return (B_TRUE);
519 }
520
521 /*
522 * We have a new packet that seems to require a new NAT flow. Construct that
523 * flow now, and intern it as both a conn_t in IP *and* in the vnet's
524 * appropriate vxnv_flows* tree. Return NULL if we have a problem.
525 */
526 static vxlnat_flow_t *
527 vxlnat_new_flow(vxlnat_rule_t *rule, in6_addr_t *inner_src, in6_addr_t *dst,
528 uint32_t ports, uint8_t protocol)
529 {
530 vxlnat_vnet_t *vnet = rule->vxnr_vnet;
531 vxlnat_flow_t *flow, *oldflow;
532 avl_tree_t *flowtree;
533 krwlock_t *flowlock;
534 avl_index_t where;
535
536 flow = kmem_alloc(sizeof (*flow), KM_NOSLEEP | KM_NORMALPRI);
537 if (flow == NULL)
538 return (NULL);
539
540 flow->vxnfl_dst = *dst;
541 flow->vxnfl_src = *inner_src;
542 flow->vxnfl_ports = ports;
543 flow->vxnfl_protocol = protocol;
544 flow->vxnfl_refcount = 2; /* One for internment, one for caller. */
545 /* Assume no mixed-IP-version mappings for now. */
546 if (IN6_IS_ADDR_V4MAPPED(inner_src)) {
547 ASSERT(IN6_IS_ADDR_V4MAPPED(dst));
548 flow->vxnfl_isv4 = B_TRUE;
549 flowtree = &vnet->vxnv_flows_v4;
550 flowlock = &vnet->vxnv_flowv4_lock;
551 } else {
552 ASSERT(!IN6_IS_ADDR_V4MAPPED(dst));
553 flow->vxnfl_isv4 = B_FALSE;
554 /* XXX KEBE SAYS we don't do IPv6 for now. */
555 DTRACE_PROBE2(vxlnat__flow__newv6, in6_addr_t *, inner_src,
556 in6_addr_t *, dst);
557 kmem_free(flow, sizeof (*flow));
558 return (NULL);
559 }
560 VXNR_REFHOLD(rule); /* For the flow itself... */
561 flow->vxnfl_rule = rule;
562
563 rw_enter(flowlock, RW_WRITER);
564 oldflow = (vxlnat_flow_t *)avl_find(flowtree, flow, &where);
565 if (oldflow != NULL) {
566 /*
567 * Hmmm, someone put one in while we were dinking around.
568 * XXX KEBE SAYS return the old one, refheld, for now.
569 */
570 VXNR_REFRELE(rule);
571 kmem_free(flow, sizeof (*flow));
572 VXNFL_REFHOLD(oldflow);
573 flow = oldflow;
574 } else {
575 avl_insert(flowtree, flow, where);
576 /*
577 * Do conn_t magic here, except for the conn_t activation. I
578 * am aware of holding the rwlock-as-write here. We may need
579 * to move this outside the rwlock hold, and
580 * reacquire-on-failure.
581 */
582 if (!vxlnat_new_conn(flow)) {
583 ASSERT(flow->vxnfl_connp == NULL);
584 avl_remove(flowtree, flow);
585 VXNR_REFRELE(flow->vxnfl_rule);
586 kmem_free(flow, sizeof (*flow));
587 flow = NULL;
588 }
589 }
590 rw_exit(flowlock);
591
592 /* We just created this one, activate it. */
593 if (oldflow == NULL && flow != NULL)
594 vxlnat_activate_conn(flow);
595
596 return (flow);
597 }
598
599 void
600 vxlnat_flow_free(vxlnat_flow_t *flow)
601 {
602 ASSERT(flow->vxnfl_refcount == 0);
603
604 /* XXX KEBE SAYS FILL ME IN?! */
605 /* XXX KEBE ASKS ipcl_hash_remove()? */
606
607 flow->vxnfl_connp->conn_priv = NULL; /* Sufficient? */
608 CONN_DEC_REF(flow->vxnfl_connp);
609 VXNR_REFRELE(flow->vxnfl_rule);
610 kmem_free(flow, sizeof (*flow));
611 }
612
613 static boolean_t
614 vxlnat_verify_initial(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h,
615 uint32_t ports, uint8_t protocol, uint8_t *nexthdr)
616 {
617 /* XXX KEBE SAYS FILL ME IN! */
618 freemsg(mp);
619 return (B_FALSE);
620 }
621
622 /*
623 * If we reach here, we need to find a NAT rule, and see if we can/should
624 * CREATE a new NAT flow, or whether or not we should drop, maybe even
625 * returning an ICMP message of some sort.
626 *
627 * B_TRUE means the packet was handled, and we shouldn't continue processing
628 * (even if "was handled" means droppage).
629 */
630 static boolean_t
631 vxlnat_one_vxlan_rule(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
632 ip6_t *ip6h)
633 {
634 vxlnat_rule_t *rule;
635 vxlnat_flow_t *flow;
636 in6_addr_t v4m_src, v4m_dst, *inner_src, *dst;
637 uint32_t ports;
638 uint8_t protocol;
639 uint8_t *nexthdr;
640
641 /* XXX handle IPv6 later, assigning inner_src and dst to ip6_t addrs. */
642 if (ip6h != NULL)
643 return (B_FALSE);
644
645 ASSERT3P(ipha, !=, NULL);
646 inner_src = &v4m_src;
647 dst = &v4m_dst;
648 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src), inner_src);
649 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_dst), dst);
650
651 mutex_enter(&vnet->vxnv_rule_lock);
652 rule = list_head(&vnet->vxnv_rules);
653
654 /*
655 * search for a match in the nat rules
656 * XXX investigate perf issues with with respect to list_t size
657 * XXX KEBE SAYS rewrite when we start doing IPv6 to use "inner_src"
658 * and "dst".
659 */
660 while (rule != NULL) {
661 ipaddr_t ipaddr;
662 uint32_t netmask = 0xffffffff;
663 uint8_t prefix = rule->vxnr_prefix - 96;
664
665 /* calculate the v4 netmask */
666 netmask <<= (32 - prefix);
667 netmask = htonl(netmask);
668
669 IN6_V4MAPPED_TO_IPADDR(&rule->vxnr_myaddr, ipaddr);
670 /* XXX ASSERT vlanid? */
671 if ((ipaddr & netmask) == (ipha->ipha_src & netmask)) {
672 VXNR_REFHOLD(rule);
673 break;
674 }
675
676 rule = list_next(&vnet->vxnv_rules, rule);
677 }
678
679 mutex_exit(&vnet->vxnv_rule_lock);
680
681 if (rule == NULL)
682 return (B_FALSE);
683
684 /* process packet */
685
686 /*
687 * Grab transport header, and figure out if we can proceed.
688 *
689 * NOTE: vxlnat_grab_transport() will free/consume mp if it fails,
690 * because we want to isolate non-flow-starters without having them
691 * create new flows. This means we return B_TRUE (consumed mp) on
692 * failure.
693 */
694 if (!vxlnat_grab_transport(mp, ipha, ip6h, &ports, &protocol, &nexthdr))
695 return (B_TRUE); /* see above... */
696 if (!vxlnat_verify_initial(mp, ipha, ip6h, ports, protocol, nexthdr))
697 return (B_TRUE);
698
699
700 flow = vxlnat_new_flow(rule, inner_src, dst, ports, protocol);
701 if (flow != NULL) {
702 /*
703 * Call same function that vxlnat_one_vxlan_flow() uses
704 * to remap & transmit the packet out the external side.
705 *
706 * NOTE: We've already checked the initial-packet-
707 * qualification, so unlike the main datapath, we don't
708 * need to call vxlnat_verify_natstate()
709 */
710
711 /* XXX KEBE SAYS PROCESS... */
712
713 VXNFL_REFRELE(flow);
714 return (B_TRUE);
715 }
716
717 return (B_FALSE);
718 }
719
720 /*
721 * See if the inbound VXLAN packet hits a 1-1/fixed mapping, and process if it
722 * does. B_TRUE means the packet was handled, and we shouldn't continue
723 * processing (even if "was handled" means droppage).
724 */
725 static boolean_t
726 vxlnat_one_vxlan_fixed(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
727 ip6_t *ip6h)
728 {
729 vxlnat_fixed_t *fixed, fsearch;
730 mblk_t *newmp;
731 ire_t *outbound_ire;
732 /* Use C99's initializers for fun & profit. */
733 ip_recv_attr_t iras = { IRAF_IS_IPV4 | IRAF_VERIFIED_SRC };
734
735 if (ipha != NULL) {
736 IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src),
836 if (vxh->vxlan_flags != VXLAN_F_VDI_WIRE) {
837 DTRACE_PROBE1(vxlnat__in__drop__VDI, mblk_t *, mp);
838 freemsg(mp);
839 return;
840 }
841
842 /* Remember, we key off of what's on the wire. */
843 vnet = vxlnat_get_vnet(VXLAN_ID_WIRE32(vxh->vxlan_id), B_FALSE);
844 if (vnet == NULL) {
845 DTRACE_PROBE1(vxlnat__in__drop__vnetid, uint32_t,
846 VXLAN_ID_HTON(VXLAN_ID_WIRE32(vxh->vxlan_id)));
847 freemsg(mp);
848 return;
849 }
850
851 DTRACE_PROBE2(vxlnat__in__vnet, uint32_t,
852 VXLAN_ID_HTON(VXLAN_ID_WIRE32(vxh->vxlan_id)),
853 vxlnat_vnet_t, vnet);
854
855 /*
856 * Arrived-from-vxlan processing steps:
857 * 1.) Locate the ethernet header and check/update/add-into remotes.
858 * 2.) Search 1-1s, process if hit.
859 * 3.) Search flows, process if hit.
860 * 4.) Search rules, create new flow (or not) if hit.
861 * 5.) Drop the packet.
862 */
863
864 /* 1.) Locate the ethernet header and check/update/add-into remotes. */
865 mp->b_rptr += sizeof (*vxh);
866 while (MBLKL(mp) == 0) {
867 mblk_t *oldmp = mp;
868
869 mp = mp->b_cont;
870 freeb(oldmp);
871 }
872 mp = vxlnat_cache_remote(mp, underlay_src, vnet);
873 if (mp == NULL)
874 goto bail_no_free;
875
876 /* Let's cache the IP header here... */
877 ipha = (ipha_t *)mp->b_rptr;
878 switch (IPH_HDR_VERSION(ipha)) {
879 case IPV4_VERSION:
880 ip6h = NULL;
881 break;
|