373 } svl_vl2;
374 struct svl_lookup_vl3 {
375 varpd_arp_handle_t *svl_vah;
376 uint8_t *svl_out;
377 } svl_vl3;
378 struct svl_lookup_route {
379 varpd_query_handle_t *svl_handle;
380 overlay_target_point_t *svl_point;
381 overlay_target_route_t *svl_route;
382 } svl_route;
383 } svl_u;
384 svp_query_t svl_query;
385 } svp_lookup_t;
386
387 static const char *varpd_svp_props[] = {
388 "svp/host",
389 "svp/port",
390 "svp/underlay_ip",
391 "svp/underlay_port",
392 "svp/dcid",
393 "svp/router_mac"
394 };
395
396 static const uint8_t svp_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
397
398 int
399 svp_comparator(const void *l, const void *r)
400 {
401 const svp_t *ls = l;
402 const svp_t *rs = r;
403
404 if (ls->svp_vid > rs->svp_vid)
405 return (1);
406 if (ls->svp_vid < rs->svp_vid)
407 return (-1);
408 return (0);
409 }
410
411 static void
412 svp_vl2_lookup_cb(svp_t *svp, svp_status_t status, const struct in6_addr *uip,
413 const uint16_t uport, void *arg)
422 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
423 VARPD_LOOKUP_DROP);
424 umem_cache_free(svp_lookup_cache, svl);
425 return;
426 }
427
428 otp = svl->svl_u.svl_vl2.svl_point;
429 bcopy(uip, &otp->otp_ip, sizeof (struct in6_addr));
430 otp->otp_port = uport;
431 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
432 VARPD_LOOKUP_OK);
433 umem_cache_free(svp_lookup_cache, svl);
434 }
435
436 static void
437 svp_vl3_lookup_cb(svp_t *svp, svp_status_t status, const uint8_t *vl2mac,
438 const struct in6_addr *uip, const uint16_t uport, void *arg)
439 {
440 overlay_target_point_t point;
441 svp_lookup_t *svl = arg;
442
443 assert(svp != NULL);
444 assert(svl != NULL);
445
446 if (status != SVP_S_OK) {
447 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
448 VARPD_LOOKUP_DROP);
449 umem_cache_free(svp_lookup_cache, svl);
450 return;
451 }
452
453 /* Inject the L2 mapping before the L3 */
454 bcopy(uip, &point.otp_ip, sizeof (struct in6_addr));
455 point.otp_port = uport;
456 libvarpd_inject_varp(svp->svp_hdl, vl2mac, &point);
457
458 bcopy(vl2mac, svl->svl_u.svl_vl3.svl_out, ETHERADDRL);
459 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
460 VARPD_LOOKUP_OK);
461 umem_cache_free(svp_lookup_cache, svl);
462 }
463
464 static void
465 svp_vl2_invalidate_cb(svp_t *svp, const uint8_t *vl2mac)
466 {
467 libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
468 }
469
470 static void
471 svp_vl3_inject_cb(svp_t *svp, const uint16_t vlan, const struct in6_addr *vl3ip,
472 const uint8_t *vl2mac, const uint8_t *targmac)
473 {
474 struct in_addr v4;
475
476 /*
792 break;
793 case 3:
794 /* svp/underlay_port */
795 libvarpd_prop_set_name(vph, varpd_svp_props[3]);
796 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
797 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
798 (void) libvarpd_prop_set_default(vph, &svp_defuport,
799 sizeof (svp_defuport));
800 libvarpd_prop_set_range_uint32(vph, 1, UINT16_MAX);
801 break;
802 case 4:
803 /* svp/dcid */
804 libvarpd_prop_set_name(vph, varpd_svp_props[4]);
805 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
806 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
807 libvarpd_prop_set_nodefault(vph);
808 /* XXX KEBE ASKS should I just set high to UINT32_MAX? */
809 libvarpd_prop_set_range_uint32(vph, 1, UINT32_MAX - 1);
810 break;
811 case 5:
812 /* svp/router_mac */
813 libvarpd_prop_set_name(vph, varpd_svp_props[5]);
814 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
815 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_ETHER);
816 libvarpd_prop_set_nodefault(vph);
817 break;
818 default:
819 return (EINVAL);
820 }
821 return (0);
822 }
823
824 static int
825 varpd_svp_getprop(void *arg, const char *pname, void *buf, uint32_t *sizep)
826 {
827 svp_t *svp = arg;
828
829 /* svp/host */
830 if (strcmp(pname, varpd_svp_props[0]) == 0) {
831 size_t len;
832
903 /* svp/dcid */
904 if (strcmp(pname, varpd_svp_props[4]) == 0) {
905 uint64_t val;
906
907 if (*sizep < sizeof (uint64_t))
908 return (EOVERFLOW);
909
910 mutex_enter(&svp->svp_lock);
911 if (svp->svp_uport == 0) {
912 *sizep = 0;
913 } else {
914 val = svp->svp_dcid;
915 bcopy(&val, buf, sizeof (uint64_t));
916 *sizep = sizeof (uint64_t);
917 }
918
919 mutex_exit(&svp->svp_lock);
920 return (0);
921 }
922
923 /* svp/router_mac */
924 if (strcmp(pname, varpd_svp_props[5]) == 0) {
925 if (*sizep < ETHERADDRL)
926 return (EOVERFLOW);
927 mutex_enter(&svp->svp_lock);
928
929 if (ether_is_zero(&svp->svp_router_mac)) {
930 *sizep = 0;
931 } else {
932 bcopy(&svp->svp_router_mac, buf, ETHERADDRL);
933 *sizep = ETHERADDRL;
934 }
935
936 mutex_exit(&svp->svp_lock);
937 return (0);
938 }
939 return (EINVAL);
940 }
941
942 static int
943 varpd_svp_setprop(void *arg, const char *pname, const void *buf,
944 const uint32_t size)
945 {
946 svp_t *svp = arg;
947
948 /* svp/host */
949 if (strcmp(pname, varpd_svp_props[0]) == 0) {
950 char *dup;
951 dup = umem_alloc(size, UMEM_DEFAULT);
952 (void) strlcpy(dup, buf, size);
1021 return (0);
1022 }
1023
1024 /* svp/dcid */
1025 if (strcmp(pname, varpd_svp_props[4]) == 0) {
1026 const uint64_t *valp = buf;
1027 if (size < sizeof (uint64_t))
1028 return (EOVERFLOW);
1029
1030 /* XXX KEBE ASKS, use UINT32_MAX instead? */
1031 if (*valp == 0 || *valp > UINT32_MAX - 1)
1032 return (EINVAL);
1033
1034 mutex_enter(&svp->svp_lock);
1035 svp->svp_dcid = (uint32_t)*valp;
1036 mutex_exit(&svp->svp_lock);
1037
1038 return (0);
1039 }
1040
1041 /* svp/router_mac */
1042 if (strcmp(pname, varpd_svp_props[5]) == 0) {
1043 if (size < ETHERADDRL)
1044 return (EOVERFLOW);
1045 mutex_enter(&svp->svp_lock);
1046 bcopy(buf, &svp->svp_router_mac, ETHERADDRL);
1047 mutex_exit(&svp->svp_lock);
1048 return (0);
1049 }
1050
1051 return (EINVAL);
1052 }
1053
1054 static int
1055 varpd_svp_save(void *arg, nvlist_t *nvp)
1056 {
1057 int ret;
1058 svp_t *svp = arg;
1059
1060 mutex_enter(&svp->svp_lock);
1061 /* svp/host */
1062 if (svp->svp_host != NULL) {
1063 if ((ret = nvlist_add_string(nvp, varpd_svp_props[0],
1064 svp->svp_host)) != 0) {
1065 mutex_exit(&svp->svp_lock);
1066 return (ret);
1093 }
1094
1095 /* svp/underlay_port */
1096 if (svp->svp_uport != 0) {
1097 if ((ret = nvlist_add_uint16(nvp, varpd_svp_props[3],
1098 svp->svp_uport)) != 0) {
1099 mutex_exit(&svp->svp_lock);
1100 return (ret);
1101 }
1102 }
1103
1104 /* svp/dcid */
1105 if (svp->svp_dcid != 0) {
1106 if ((ret = nvlist_add_uint32(nvp, varpd_svp_props[4],
1107 svp->svp_dcid)) != 0) {
1108 mutex_exit(&svp->svp_lock);
1109 return (ret);
1110 }
1111 }
1112
1113 /* svp/router_mac */
1114 if (!ether_is_zero(&svp->svp_router_mac)) {
1115 char buf[ETHERADDRSTRL];
1116
1117 /* XXX KEBE SAYS See underlay_ip... */
1118 if (ether_ntoa_r(&svp->svp_router_mac, buf) == NULL) {
1119 libvarpd_panic("unexpected ether_ntoa_r failure: %d",
1120 errno);
1121 }
1122
1123 if ((ret = nvlist_add_string(nvp, varpd_svp_props[5],
1124 buf)) != 0) {
1125 mutex_exit(&svp->svp_lock);
1126 return (ret);
1127 }
1128 }
1129
1130 mutex_exit(&svp->svp_lock);
1131 return (0);
1132 }
1133
1134 static int
1135 varpd_svp_restore(nvlist_t *nvp, varpd_provider_handle_t *hdl,
1136 overlay_plugin_dest_t dest, void **outp)
1137 {
1138 int ret;
1195 /* svp/underlay_port */
1196 if ((ret = nvlist_lookup_uint16(nvp, varpd_svp_props[3],
1197 &svp->svp_uport)) != 0) {
1198 if (ret != ENOENT) {
1199 varpd_svp_destroy(svp);
1200 return (ret);
1201 }
1202 svp->svp_uport = 0;
1203 }
1204
1205 /* svp/dcid */
1206 if ((ret = nvlist_lookup_uint32(nvp, varpd_svp_props[4],
1207 &svp->svp_dcid)) != 0) {
1208 if (ret != ENOENT) {
1209 varpd_svp_destroy(svp);
1210 return (ret);
1211 }
1212 svp->svp_dcid = 0;
1213 }
1214
1215 /* svp/router_mac */
1216 if ((ret = nvlist_lookup_string(nvp, varpd_svp_props[5],
1217 ðerstr)) != 0) {
1218 if (ret != ENOENT) {
1219 varpd_svp_destroy(svp);
1220 return (ret);
1221 }
1222 bzero(&svp->svp_router_mac, ETHERADDRL);
1223 } else if (ether_aton_r(etherstr, &svp->svp_router_mac) == NULL) {
1224 libvarpd_panic("unexpected ether_aton_r failure: %d", errno);
1225 }
1226
1227 svp->svp_hdl = hdl;
1228 *outp = svp;
1229 return (0);
1230 }
1231
1232 static void
1233 varpd_svp_arp(void *arg, varpd_arp_handle_t *vah, int type,
1234 const struct sockaddr *sock, uint8_t *out)
1235 {
1236 svp_t *svp = arg;
1237 svp_lookup_t *svl;
1238
1239 if (type != VARPD_QTYPE_ETHERNET) {
1240 libvarpd_plugin_arp_reply(vah, VARPD_LOOKUP_DROP);
1241 return;
1242 }
1243
|
373 } svl_vl2;
374 struct svl_lookup_vl3 {
375 varpd_arp_handle_t *svl_vah;
376 uint8_t *svl_out;
377 } svl_vl3;
378 struct svl_lookup_route {
379 varpd_query_handle_t *svl_handle;
380 overlay_target_point_t *svl_point;
381 overlay_target_route_t *svl_route;
382 } svl_route;
383 } svl_u;
384 svp_query_t svl_query;
385 } svp_lookup_t;
386
387 static const char *varpd_svp_props[] = {
388 "svp/host",
389 "svp/port",
390 "svp/underlay_ip",
391 "svp/underlay_port",
392 "svp/dcid",
393 "svp/router_oui"
394 };
395
396 static const uint8_t svp_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
397
398 int
399 svp_comparator(const void *l, const void *r)
400 {
401 const svp_t *ls = l;
402 const svp_t *rs = r;
403
404 if (ls->svp_vid > rs->svp_vid)
405 return (1);
406 if (ls->svp_vid < rs->svp_vid)
407 return (-1);
408 return (0);
409 }
410
411 static void
412 svp_vl2_lookup_cb(svp_t *svp, svp_status_t status, const struct in6_addr *uip,
413 const uint16_t uport, void *arg)
422 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
423 VARPD_LOOKUP_DROP);
424 umem_cache_free(svp_lookup_cache, svl);
425 return;
426 }
427
428 otp = svl->svl_u.svl_vl2.svl_point;
429 bcopy(uip, &otp->otp_ip, sizeof (struct in6_addr));
430 otp->otp_port = uport;
431 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
432 VARPD_LOOKUP_OK);
433 umem_cache_free(svp_lookup_cache, svl);
434 }
435
436 static void
437 svp_vl3_lookup_cb(svp_t *svp, svp_status_t status, const uint8_t *vl2mac,
438 const struct in6_addr *uip, const uint16_t uport, void *arg)
439 {
440 overlay_target_point_t point;
441 svp_lookup_t *svl = arg;
442 uint8_t nexthop_mac[6] = { 0, 0, 0, 0, 0, 0 };
443
444 assert(svp != NULL);
445 assert(svl != NULL);
446
447 if (status != SVP_S_OK) {
448 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
449 VARPD_LOOKUP_DROP);
450 umem_cache_free(svp_lookup_cache, svl);
451 return;
452 }
453
454 /* Inject the L2 mapping before the L3 */
455 bcopy(uip, &point.otp_ip, sizeof (struct in6_addr));
456 point.otp_port = uport;
457 if (uport != 0) {
458 /* Normal L3 lookup result... */
459 libvarpd_inject_varp(svp->svp_hdl, vl2mac, &point);
460 } else {
461 /*
462 * Oh my, we have a next-hop router IP.
463 * Set the MAC to the ouid+vid concatenated
464 * special-router-MAC. Overlay down below will know
465 * that uport == 0 means the MAC is a special one.
466 */
467 if (bcmp(svp->svp_router_oui, nexthop_mac, ETHERADDRL) == 0) {
468 /*
469 * We don't have a router_oui, so we can't support
470 * special-router-MAC. Drop it.
471 */
472 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
473 VARPD_LOOKUP_DROP);
474 umem_cache_free(svp_lookup_cache, svl);
475 return;
476 }
477 vl2mac = nexthop_mac;
478 bcopy(svp->svp_router_oui, vl2mac, 3);
479 vl2mac[3] = (svp->svp_vid >> 16) & 0xff;
480 vl2mac[4] = (svp->svp_vid >> 8) & 0xff;
481 vl2mac[5] = svp->svp_vid & 0xff;
482 }
483
484 bcopy(vl2mac, svl->svl_u.svl_vl3.svl_out, ETHERADDRL);
485 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
486 VARPD_LOOKUP_OK);
487 umem_cache_free(svp_lookup_cache, svl);
488 }
489
490 static void
491 svp_vl2_invalidate_cb(svp_t *svp, const uint8_t *vl2mac)
492 {
493 libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
494 }
495
496 static void
497 svp_vl3_inject_cb(svp_t *svp, const uint16_t vlan, const struct in6_addr *vl3ip,
498 const uint8_t *vl2mac, const uint8_t *targmac)
499 {
500 struct in_addr v4;
501
502 /*
818 break;
819 case 3:
820 /* svp/underlay_port */
821 libvarpd_prop_set_name(vph, varpd_svp_props[3]);
822 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
823 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
824 (void) libvarpd_prop_set_default(vph, &svp_defuport,
825 sizeof (svp_defuport));
826 libvarpd_prop_set_range_uint32(vph, 1, UINT16_MAX);
827 break;
828 case 4:
829 /* svp/dcid */
830 libvarpd_prop_set_name(vph, varpd_svp_props[4]);
831 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
832 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
833 libvarpd_prop_set_nodefault(vph);
834 /* XXX KEBE ASKS should I just set high to UINT32_MAX? */
835 libvarpd_prop_set_range_uint32(vph, 1, UINT32_MAX - 1);
836 break;
837 case 5:
838 /* svp/router_oui */
839 libvarpd_prop_set_name(vph, varpd_svp_props[5]);
840 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
841 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_ETHER);
842 libvarpd_prop_set_nodefault(vph);
843 break;
844 default:
845 return (EINVAL);
846 }
847 return (0);
848 }
849
850 static int
851 varpd_svp_getprop(void *arg, const char *pname, void *buf, uint32_t *sizep)
852 {
853 svp_t *svp = arg;
854
855 /* svp/host */
856 if (strcmp(pname, varpd_svp_props[0]) == 0) {
857 size_t len;
858
929 /* svp/dcid */
930 if (strcmp(pname, varpd_svp_props[4]) == 0) {
931 uint64_t val;
932
933 if (*sizep < sizeof (uint64_t))
934 return (EOVERFLOW);
935
936 mutex_enter(&svp->svp_lock);
937 if (svp->svp_uport == 0) {
938 *sizep = 0;
939 } else {
940 val = svp->svp_dcid;
941 bcopy(&val, buf, sizeof (uint64_t));
942 *sizep = sizeof (uint64_t);
943 }
944
945 mutex_exit(&svp->svp_lock);
946 return (0);
947 }
948
949 /* svp/router_oui */
950 if (strcmp(pname, varpd_svp_props[5]) == 0) {
951 if (*sizep < ETHERADDRL)
952 return (EOVERFLOW);
953 mutex_enter(&svp->svp_lock);
954
955 if (ether_is_zero(&svp->svp_router_oui)) {
956 *sizep = 0;
957 } else {
958 bcopy(&svp->svp_router_oui, buf, ETHERADDRL);
959 *sizep = ETHERADDRL;
960 }
961
962 mutex_exit(&svp->svp_lock);
963 return (0);
964 }
965 return (EINVAL);
966 }
967
968 static int
969 varpd_svp_setprop(void *arg, const char *pname, const void *buf,
970 const uint32_t size)
971 {
972 svp_t *svp = arg;
973
974 /* svp/host */
975 if (strcmp(pname, varpd_svp_props[0]) == 0) {
976 char *dup;
977 dup = umem_alloc(size, UMEM_DEFAULT);
978 (void) strlcpy(dup, buf, size);
1047 return (0);
1048 }
1049
1050 /* svp/dcid */
1051 if (strcmp(pname, varpd_svp_props[4]) == 0) {
1052 const uint64_t *valp = buf;
1053 if (size < sizeof (uint64_t))
1054 return (EOVERFLOW);
1055
1056 /* XXX KEBE ASKS, use UINT32_MAX instead? */
1057 if (*valp == 0 || *valp > UINT32_MAX - 1)
1058 return (EINVAL);
1059
1060 mutex_enter(&svp->svp_lock);
1061 svp->svp_dcid = (uint32_t)*valp;
1062 mutex_exit(&svp->svp_lock);
1063
1064 return (0);
1065 }
1066
1067 /* svp/router_oui */
1068 if (strcmp(pname, varpd_svp_props[5]) == 0) {
1069 if (size < ETHERADDRL)
1070 return (EOVERFLOW);
1071 mutex_enter(&svp->svp_lock);
1072 bcopy(buf, &svp->svp_router_oui, ETHERADDRL);
1073 /* Zero-out the low three bytes. */
1074 svp->svp_router_oui[3] = 0;
1075 svp->svp_router_oui[4] = 0;
1076 svp->svp_router_oui[5] = 0;
1077 mutex_exit(&svp->svp_lock);
1078 return (0);
1079 }
1080
1081 return (EINVAL);
1082 }
1083
1084 static int
1085 varpd_svp_save(void *arg, nvlist_t *nvp)
1086 {
1087 int ret;
1088 svp_t *svp = arg;
1089
1090 mutex_enter(&svp->svp_lock);
1091 /* svp/host */
1092 if (svp->svp_host != NULL) {
1093 if ((ret = nvlist_add_string(nvp, varpd_svp_props[0],
1094 svp->svp_host)) != 0) {
1095 mutex_exit(&svp->svp_lock);
1096 return (ret);
1123 }
1124
1125 /* svp/underlay_port */
1126 if (svp->svp_uport != 0) {
1127 if ((ret = nvlist_add_uint16(nvp, varpd_svp_props[3],
1128 svp->svp_uport)) != 0) {
1129 mutex_exit(&svp->svp_lock);
1130 return (ret);
1131 }
1132 }
1133
1134 /* svp/dcid */
1135 if (svp->svp_dcid != 0) {
1136 if ((ret = nvlist_add_uint32(nvp, varpd_svp_props[4],
1137 svp->svp_dcid)) != 0) {
1138 mutex_exit(&svp->svp_lock);
1139 return (ret);
1140 }
1141 }
1142
1143 /* svp/router_oui */
1144 if (!ether_is_zero(&svp->svp_router_oui)) {
1145 char buf[ETHERADDRSTRL];
1146
1147 /* XXX KEBE SAYS See underlay_ip... */
1148 if (ether_ntoa_r(&svp->svp_router_oui, buf) == NULL) {
1149 libvarpd_panic("unexpected ether_ntoa_r failure: %d",
1150 errno);
1151 }
1152
1153 if ((ret = nvlist_add_string(nvp, varpd_svp_props[5],
1154 buf)) != 0) {
1155 mutex_exit(&svp->svp_lock);
1156 return (ret);
1157 }
1158 }
1159
1160 mutex_exit(&svp->svp_lock);
1161 return (0);
1162 }
1163
1164 static int
1165 varpd_svp_restore(nvlist_t *nvp, varpd_provider_handle_t *hdl,
1166 overlay_plugin_dest_t dest, void **outp)
1167 {
1168 int ret;
1225 /* svp/underlay_port */
1226 if ((ret = nvlist_lookup_uint16(nvp, varpd_svp_props[3],
1227 &svp->svp_uport)) != 0) {
1228 if (ret != ENOENT) {
1229 varpd_svp_destroy(svp);
1230 return (ret);
1231 }
1232 svp->svp_uport = 0;
1233 }
1234
1235 /* svp/dcid */
1236 if ((ret = nvlist_lookup_uint32(nvp, varpd_svp_props[4],
1237 &svp->svp_dcid)) != 0) {
1238 if (ret != ENOENT) {
1239 varpd_svp_destroy(svp);
1240 return (ret);
1241 }
1242 svp->svp_dcid = 0;
1243 }
1244
1245 /* svp/router_oui */
1246 if ((ret = nvlist_lookup_string(nvp, varpd_svp_props[5],
1247 ðerstr)) != 0) {
1248 if (ret != ENOENT) {
1249 varpd_svp_destroy(svp);
1250 return (ret);
1251 }
1252 bzero(&svp->svp_router_oui, ETHERADDRL);
1253 } else if (ether_aton_r(etherstr, &svp->svp_router_oui) == NULL) {
1254 libvarpd_panic("unexpected ether_aton_r failure: %d", errno);
1255 }
1256
1257 svp->svp_hdl = hdl;
1258 *outp = svp;
1259 return (0);
1260 }
1261
1262 static void
1263 varpd_svp_arp(void *arg, varpd_arp_handle_t *vah, int type,
1264 const struct sockaddr *sock, uint8_t *out)
1265 {
1266 svp_t *svp = arg;
1267 svp_lookup_t *svl;
1268
1269 if (type != VARPD_QTYPE_ETHERNET) {
1270 libvarpd_plugin_arp_reply(vah, VARPD_LOOKUP_DROP);
1271 return;
1272 }
1273
|