592 ifp->sysindex = sysindex; 593 strcpy(ifp->name, name); 594 strcpy(ifp->descr, name); 595 ifp->spec_oid = oid_zeroDotZero; 596 597 map = NULL; 598 if (!mib_if_is_dyn(ifp->name)) { 599 /* non-dynamic. look whether we know the interface */ 600 STAILQ_FOREACH(map, &mibindexmap_list, link) 601 if (strcmp(map->name, ifp->name) == 0) { 602 ifp->index = map->ifindex; 603 map->mibif = ifp; 604 break; 605 } 606 /* assume it has a connector if it is not dynamic */ 607 ifp->has_connector = 1; 608 ifp->trap_enable = 1; 609 } 610 if (map == NULL) { 611 /* new interface - get new index */ 612 if (next_if_index > 0x7fffffff) 613 errx(1, "ifindex wrap"); 614 615 if ((map = malloc(sizeof(*map))) == NULL) { 616 syslog(LOG_ERR, "ifmap: %m"); 617 free(ifp); 618 return (NULL); 619 } 620 map->ifindex = next_if_index++; 621 map->sysindex = ifp->sysindex; 622 strcpy(map->name, ifp->name); 623 map->mibif = ifp; 624 STAILQ_INSERT_TAIL(&mibindexmap_list, map, link); 625 } else { 626 /* re-instantiate. Introduce a counter discontinuity */ 627 ifp->counter_disc = get_ticks(); 628 } 629 ifp->index = map->ifindex; 630 ifp->mib.ifmd_data.ifi_link_state = LINK_STATE_UNKNOWN; 631 632 INSERT_OBJECT_INT(ifp, &mibif_list); 633 mib_if_number++; 634 mib_iftable_last_change = this_tick; 635 636 /* instantiate default ifStack entries */ 637 (void)mib_ifstack_create(ifp, NULL); 638 (void)mib_ifstack_create(NULL, ifp); 639 640 return (ifp); 641} 642 643/* 644 * Inform all interested parties about a new interface 645 */ 646static void 647notify_newif(struct mibif *ifp) 648{ 649 struct newifreg *reg; 650 651 TAILQ_FOREACH(reg, &newifreg_list, link) 652 if ((*reg->func)(ifp)) 653 return; 654} 655 656/* 657 * This is called for new interfaces after we have fetched the interface 658 * MIB. If this is a broadcast interface try to guess the broadcast address 659 * depending on the interface type. 660 */ 661static void 662check_llbcast(struct mibif *ifp) 663{ 664 static u_char ether_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 665 static u_char arcnet_bcast = 0; 666 struct mibrcvaddr *rcv; 667 668 if (!(ifp->mib.ifmd_flags & IFF_BROADCAST)) 669 return; 670 671 switch (ifp->mib.ifmd_data.ifi_type) { 672 673 case IFT_ETHER: 674 case IFT_FDDI: 675 case IFT_ISO88025: 676 if (mib_find_rcvaddr(ifp->index, ether_bcast, 6) == NULL && 677 (rcv = mib_rcvaddr_create(ifp, ether_bcast, 6)) != NULL) 678 rcv->flags |= MIBRCVADDR_BCAST; 679 break; 680 681 case IFT_ARCNET: 682 if (mib_find_rcvaddr(ifp->index, &arcnet_bcast, 1) == NULL && 683 (rcv = mib_rcvaddr_create(ifp, &arcnet_bcast, 1)) != NULL) 684 rcv->flags |= MIBRCVADDR_BCAST; 685 break; 686 } 687} 688 689 690/* 691 * Retrieve the current interface list from the system. 692 */ 693void 694mib_refresh_iflist(void) 695{ 696 struct mibif *ifp, *ifp1; 697 size_t len; 698 u_short idx; 699 int name[6]; 700 int count; 701 struct ifmibdata mib; 702 703 TAILQ_FOREACH(ifp, &mibif_list, link) 704 ifp->flags &= ~MIBIF_FOUND; 705 706 len = sizeof(count); 707 if (sysctlbyname("net.link.generic.system.ifcount", &count, &len, 708 NULL, 0) == -1) { 709 syslog(LOG_ERR, "ifcount: %m"); 710 return; 711 } 712 name[0] = CTL_NET; 713 name[1] = PF_LINK; 714 name[2] = NETLINK_GENERIC; 715 name[3] = IFMIB_IFDATA; 716 name[5] = IFDATA_GENERAL; 717 for (idx = 1; idx <= count; idx++) { 718 name[4] = idx; 719 len = sizeof(mib); 720 if (sysctl(name, 6, &mib, &len, NULL, 0) == -1) { 721 if (errno == ENOENT) 722 continue; 723 syslog(LOG_ERR, "ifmib(%u): %m", idx); 724 return; 725 } 726 if ((ifp = mib_find_if_sys(idx)) != NULL) { 727 ifp->flags |= MIBIF_FOUND; 728 continue; 729 } 730 /* Unknown interface - create */ 731 if ((ifp = mibif_create(idx, mib.ifmd_name)) != NULL) { 732 ifp->flags |= MIBIF_FOUND; 733 (void)mib_fetch_ifmib(ifp); 734 check_llbcast(ifp); 735 notify_newif(ifp); 736 } 737 } 738 739 /* 740 * Purge interfaces that disappeared 741 */ 742 ifp = TAILQ_FIRST(&mibif_list); 743 while (ifp != NULL) { 744 ifp1 = TAILQ_NEXT(ifp, link); 745 if (!(ifp->flags & MIBIF_FOUND)) 746 mibif_free(ifp); 747 ifp = ifp1; 748 } 749} 750 751/* 752 * Find an interface address 753 */ 754struct mibifa * 755mib_find_ifa(struct in_addr addr) 756{ 757 struct mibifa *ifa; 758 759 TAILQ_FOREACH(ifa, &mibifa_list, link) 760 if (ifa->inaddr.s_addr == addr.s_addr) 761 return (ifa); 762 return (NULL); 763} 764 765/* 766 * Process a new ARP entry 767 */ 768static void 769process_arp(const struct rt_msghdr *rtm, const struct sockaddr_dl *sdl, 770 const struct sockaddr_in *sa) 771{ 772 struct mibif *ifp; 773 struct mibarp *at; 774 775 /* IP arp table entry */ 776 if (sdl->sdl_alen == 0) { 777 update_arp = 1; 778 return; 779 } 780 if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) 781 return; 782 /* have a valid entry */ 783 if ((at = mib_find_arp(ifp, sa->sin_addr)) == NULL && 784 (at = mib_arp_create(ifp, sa->sin_addr, 785 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) 786 return; 787 788 if (rtm->rtm_rmx.rmx_expire == 0) 789 at->flags |= MIBARP_PERM; 790 else 791 at->flags &= ~MIBARP_PERM; 792 at->flags |= MIBARP_FOUND; 793} 794 795/* 796 * Handle a routing socket message. 797 */ 798static void 799handle_rtmsg(struct rt_msghdr *rtm) 800{ 801 struct sockaddr *addrs[RTAX_MAX]; 802 struct if_msghdr *ifm; 803 struct ifa_msghdr *ifam; 804 struct ifma_msghdr *ifmam; 805#ifdef RTM_IFANNOUNCE 806 struct if_announcemsghdr *ifan; 807#endif 808 struct mibif *ifp; 809 struct sockaddr_dl *sdl; 810 struct sockaddr_in *sa; 811 struct mibifa *ifa; 812 struct mibrcvaddr *rcv; 813 u_char *ptr; 814 815 if (rtm->rtm_version != RTM_VERSION) { 816 syslog(LOG_ERR, "Bogus RTM version %u", rtm->rtm_version); 817 return; 818 } 819 820 switch (rtm->rtm_type) { 821 822 case RTM_NEWADDR: 823 ifam = (struct ifa_msghdr *)rtm; 824 mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs); 825 if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) 826 break; 827 828 sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; 829 if ((ifa = mib_find_ifa(sa->sin_addr)) == NULL) { 830 /* unknown address */ 831 if ((ifp = mib_find_if_sys(ifam->ifam_index)) == NULL) { 832 syslog(LOG_WARNING, "RTM_NEWADDR for unknown " 833 "interface %u", ifam->ifam_index); 834 break; 835 } 836 if ((ifa = alloc_ifa(ifp->index, sa->sin_addr)) == NULL) 837 break; 838 } 839 sa = (struct sockaddr_in *)(void *)addrs[RTAX_NETMASK]; 840 ifa->inmask = sa->sin_addr; 841 842 if (addrs[RTAX_BRD] != NULL) { 843 sa = (struct sockaddr_in *)(void *)addrs[RTAX_BRD]; 844 ifa->inbcast = sa->sin_addr; 845 } 846 ifa->flags |= MIBIFA_FOUND; 847 break; 848 849 case RTM_DELADDR: 850 ifam = (struct ifa_msghdr *)rtm; 851 mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs); 852 if (addrs[RTAX_IFA] == NULL) 853 break; 854 855 sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; 856 if ((ifa = mib_find_ifa(sa->sin_addr)) != NULL) { 857 ifa->flags |= MIBIFA_FOUND; 858 if (!(ifa->flags & MIBIFA_DESTROYED)) 859 destroy_ifa(ifa); 860 } 861 break; 862 863 case RTM_NEWMADDR: 864 ifmam = (struct ifma_msghdr *)rtm; 865 mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); 866 if (addrs[RTAX_IFA] == NULL || 867 addrs[RTAX_IFA]->sa_family != AF_LINK) 868 break; 869 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; 870 if ((rcv = mib_find_rcvaddr(sdl->sdl_index, 871 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) { 872 /* unknown address */ 873 if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) { 874 syslog(LOG_WARNING, "RTM_NEWMADDR for unknown " 875 "interface %u", sdl->sdl_index); 876 break; 877 } 878 if ((rcv = mib_rcvaddr_create(ifp, 879 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) 880 break; 881 rcv->flags |= MIBRCVADDR_VOLATILE; 882 } 883 rcv->flags |= MIBRCVADDR_FOUND; 884 break; 885 886 case RTM_DELMADDR: 887 ifmam = (struct ifma_msghdr *)rtm; 888 mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); 889 if (addrs[RTAX_IFA] == NULL || 890 addrs[RTAX_IFA]->sa_family != AF_LINK) 891 break; 892 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; 893 if ((rcv = mib_find_rcvaddr(sdl->sdl_index, 894 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) != NULL) 895 mib_rcvaddr_delete(rcv); 896 break; 897 898 case RTM_IFINFO: 899 ifm = (struct if_msghdr *)rtm; 900 mib_extract_addrs(ifm->ifm_addrs, (u_char *)(ifm + 1), addrs); 901 if ((ifp = mib_find_if_sys(ifm->ifm_index)) == NULL) 902 break; 903 if (addrs[RTAX_IFP] != NULL && 904 addrs[RTAX_IFP]->sa_family == AF_LINK) { 905 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFP]; 906 ptr = sdl->sdl_data + sdl->sdl_nlen; 907 get_physaddr(ifp, sdl, ptr); 908 } 909 (void)mib_fetch_ifmib(ifp); 910 break; 911 912#ifdef RTM_IFANNOUNCE 913 case RTM_IFANNOUNCE: 914 ifan = (struct if_announcemsghdr *)rtm; 915 ifp = mib_find_if_sys(ifan->ifan_index); 916 917 switch (ifan->ifan_what) { 918 919 case IFAN_ARRIVAL: 920 if (ifp == NULL && (ifp = mibif_create(ifan->ifan_index, 921 ifan->ifan_name)) != NULL) { 922 (void)mib_fetch_ifmib(ifp); 923 check_llbcast(ifp); 924 notify_newif(ifp); 925 } 926 break; 927 928 case IFAN_DEPARTURE: 929 if (ifp != NULL) 930 mibif_free(ifp); 931 break; 932 } 933 break; 934#endif 935 936 case RTM_GET: 937 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 938 if (rtm->rtm_flags & RTF_LLINFO) { 939 if (addrs[RTAX_DST] == NULL || 940 addrs[RTAX_GATEWAY] == NULL || 941 addrs[RTAX_DST]->sa_family != AF_INET || 942 addrs[RTAX_GATEWAY]->sa_family != AF_LINK) 943 break; 944 process_arp(rtm, 945 (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY], 946 (struct sockaddr_in *)(void *)addrs[RTAX_DST]); 947 } else { 948 if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) 949 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 950 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 951 } 952 break; 953 954 case RTM_ADD: 955 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 956 if (rtm->rtm_flags & RTF_LLINFO) { 957 if (addrs[RTAX_DST] == NULL || 958 addrs[RTAX_GATEWAY] == NULL || 959 addrs[RTAX_DST]->sa_family != AF_INET || 960 addrs[RTAX_GATEWAY]->sa_family != AF_LINK) 961 break; 962 process_arp(rtm, 963 (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY], 964 (struct sockaddr_in *)(void *)addrs[RTAX_DST]); 965 } else { 966 if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) 967 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 968 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 969 } 970 break; 971 972 case RTM_DELETE: 973 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 974 if (rtm->rtm_errno == 0 && !(rtm->rtm_flags & RTF_LLINFO)) 975 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 976 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 977 break; 978 } 979} 980 981/* 982 * send a routing message 983 */ 984void 985mib_send_rtmsg(struct rt_msghdr *rtm, struct sockaddr *gw, 986 struct sockaddr *dst, struct sockaddr *mask) 987{ 988 size_t len; 989 struct rt_msghdr *msg; 990 char *cp; 991 ssize_t sent; 992 993 len = sizeof(*rtm) + SA_SIZE(gw) + SA_SIZE(dst) + SA_SIZE(mask); 994 if ((msg = malloc(len)) == NULL) { 995 syslog(LOG_ERR, "%s: %m", __func__); 996 return; 997 } 998 cp = (char *)(msg + 1); 999 1000 memset(msg, 0, sizeof(*msg)); 1001 msg->rtm_flags = 0; 1002 msg->rtm_version = RTM_VERSION; 1003 msg->rtm_addrs = RTA_DST | RTA_GATEWAY; 1004 1005 memcpy(cp, dst, SA_SIZE(dst)); 1006 cp += SA_SIZE(dst); 1007 memcpy(cp, gw, SA_SIZE(gw)); 1008 cp += SA_SIZE(gw); 1009 if (mask != NULL) { 1010 memcpy(cp, mask, SA_SIZE(mask)); 1011 cp += SA_SIZE(mask); 1012 msg->rtm_addrs |= RTA_NETMASK; 1013 } 1014 msg->rtm_msglen = cp - (char *)msg; 1015 msg->rtm_type = RTM_GET; 1016 if ((sent = write(route, msg, msg->rtm_msglen)) == -1) { 1017 syslog(LOG_ERR, "%s: write: %m", __func__); 1018 free(msg); 1019 return; 1020 } 1021 if (sent != msg->rtm_msglen) { 1022 syslog(LOG_ERR, "%s: short write", __func__); 1023 free(msg); 1024 return; 1025 } 1026 free(msg); 1027} 1028 1029/* 1030 * Fetch the routing table via sysctl 1031 */ 1032u_char * 1033mib_fetch_rtab(int af, int info, int arg, size_t *lenp) 1034{ 1035 int name[6]; 1036 u_char *buf, *newbuf; 1037 1038 name[0] = CTL_NET; 1039 name[1] = PF_ROUTE; 1040 name[2] = 0; 1041 name[3] = af; 1042 name[4] = info; 1043 name[5] = arg; 1044 1045 *lenp = 0; 1046 1047 /* initial estimate */ 1048 if (sysctl(name, 6, NULL, lenp, NULL, 0) == -1) { 1049 syslog(LOG_ERR, "sysctl estimate (%d,%d,%d,%d,%d,%d): %m", 1050 name[0], name[1], name[2], name[3], name[4], name[5]); 1051 return (NULL); 1052 } 1053 if (*lenp == 0) 1054 return (NULL); 1055 1056 buf = NULL; 1057 for (;;) { 1058 if ((newbuf = realloc(buf, *lenp)) == NULL) { 1059 syslog(LOG_ERR, "sysctl buffer: %m"); 1060 free(buf); 1061 return (NULL); 1062 } 1063 buf = newbuf; 1064 1065 if (sysctl(name, 6, buf, lenp, NULL, 0) == 0) 1066 break; 1067 1068 if (errno != ENOMEM) { 1069 syslog(LOG_ERR, "sysctl get: %m"); 1070 free(buf); 1071 return (NULL); 1072 } 1073 *lenp += *lenp / 8 + 1; 1074 } 1075 1076 return (buf); 1077} 1078 1079/* 1080 * Update the following info: interface, interface addresses, interface 1081 * receive addresses, arp-table. 1082 * This does not change the interface list itself. 1083 */ 1084static void 1085update_ifa_info(void) 1086{ 1087 u_char *buf, *next; 1088 struct rt_msghdr *rtm; 1089 struct mibifa *ifa, *ifa1; 1090 struct mibrcvaddr *rcv, *rcv1; 1091 size_t needed; 1092 static const int infos[][3] = { 1093 { 0, NET_RT_IFLIST, 0 }, 1094#ifdef NET_RT_IFMALIST 1095 { AF_LINK, NET_RT_IFMALIST, 0 }, 1096#endif 1097 }; 1098 u_int i; 1099 1100 TAILQ_FOREACH(ifa, &mibifa_list, link) 1101 ifa->flags &= ~MIBIFA_FOUND; 1102 TAILQ_FOREACH(rcv, &mibrcvaddr_list, link) 1103 rcv->flags &= ~MIBRCVADDR_FOUND; 1104 1105 for (i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { 1106 if ((buf = mib_fetch_rtab(infos[i][0], infos[i][1], infos[i][2], 1107 &needed)) == NULL) 1108 continue; 1109 1110 next = buf; 1111 while (next < buf + needed) { 1112 rtm = (struct rt_msghdr *)(void *)next; 1113 next += rtm->rtm_msglen; 1114 handle_rtmsg(rtm); 1115 } 1116 free(buf); 1117 } 1118 1119 /* 1120 * Purge the address list of unused entries. These may happen for 1121 * interface aliases that are on the same subnet. We don't receive 1122 * routing socket messages for them. 1123 */ 1124 ifa = TAILQ_FIRST(&mibifa_list); 1125 while (ifa != NULL) { 1126 ifa1 = TAILQ_NEXT(ifa, link); 1127 if (!(ifa->flags & MIBIFA_FOUND)) 1128 destroy_ifa(ifa); 1129 ifa = ifa1; 1130 } 1131 1132 rcv = TAILQ_FIRST(&mibrcvaddr_list); 1133 while (rcv != NULL) { 1134 rcv1 = TAILQ_NEXT(rcv, link); 1135 if (!(rcv->flags & (MIBRCVADDR_FOUND | MIBRCVADDR_BCAST | 1136 MIBRCVADDR_HW))) 1137 mib_rcvaddr_delete(rcv); 1138 rcv = rcv1; 1139 } 1140} 1141 1142/* 1143 * Update arp table 1144 */ 1145void 1146mib_arp_update(void) 1147{ 1148 struct mibarp *at, *at1; 1149 size_t needed; 1150 u_char *buf, *next; 1151 struct rt_msghdr *rtm; 1152 1153 if (in_update_arp) 1154 return; /* Aaargh */ 1155 in_update_arp = 1; 1156 1157 TAILQ_FOREACH(at, &mibarp_list, link) 1158 at->flags &= ~MIBARP_FOUND; 1159 1160 if ((buf = mib_fetch_rtab(AF_INET, NET_RT_FLAGS, RTF_LLINFO, &needed)) == NULL) { 1161 in_update_arp = 0; 1162 return; 1163 } 1164 1165 next = buf; 1166 while (next < buf + needed) { 1167 rtm = (struct rt_msghdr *)(void *)next; 1168 next += rtm->rtm_msglen; 1169 handle_rtmsg(rtm); 1170 } 1171 free(buf); 1172 1173 at = TAILQ_FIRST(&mibarp_list); 1174 while (at != NULL) { 1175 at1 = TAILQ_NEXT(at, link); 1176 if (!(at->flags & MIBARP_FOUND)) 1177 mib_arp_delete(at); 1178 at = at1; 1179 } 1180 mibarpticks = get_ticks(); 1181 update_arp = 0; 1182 in_update_arp = 0; 1183} 1184 1185 1186/* 1187 * Intput on the routing socket. 1188 */ 1189static void 1190route_input(int fd, void *udata __unused) 1191{ 1192 u_char buf[1024 * 16]; 1193 ssize_t n; 1194 struct rt_msghdr *rtm; 1195 1196 if ((n = read(fd, buf, sizeof(buf))) == -1) 1197 err(1, "read(rt_socket)"); 1198 1199 if (n == 0) 1200 errx(1, "EOF on rt_socket"); 1201 1202 rtm = (struct rt_msghdr *)(void *)buf; 1203 if ((size_t)n != rtm->rtm_msglen) 1204 errx(1, "n=%zu, rtm_msglen=%u", (size_t)n, rtm->rtm_msglen); 1205 1206 handle_rtmsg(rtm); 1207} 1208 1209/* 1210 * execute and SIOCAIFADDR 1211 */ 1212static int 1213siocaifaddr(char *ifname, struct in_addr addr, struct in_addr mask, 1214 struct in_addr bcast) 1215{ 1216 struct ifaliasreq addreq; 1217 struct sockaddr_in *sa; 1218 1219 memset(&addreq, 0, sizeof(addreq)); 1220 strncpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); 1221 1222 sa = (struct sockaddr_in *)(void *)&addreq.ifra_addr; 1223 sa->sin_family = AF_INET; 1224 sa->sin_len = sizeof(*sa); 1225 sa->sin_addr = addr; 1226 1227 sa = (struct sockaddr_in *)(void *)&addreq.ifra_mask; 1228 sa->sin_family = AF_INET; 1229 sa->sin_len = sizeof(*sa); 1230 sa->sin_addr = mask; 1231 1232 sa = (struct sockaddr_in *)(void *)&addreq.ifra_broadaddr; 1233 sa->sin_family = AF_INET; 1234 sa->sin_len = sizeof(*sa); 1235 sa->sin_addr = bcast; 1236 1237 return (ioctl(mib_netsock, SIOCAIFADDR, &addreq)); 1238} 1239 1240/* 1241 * Exececute a SIOCDIFADDR 1242 */ 1243static int 1244siocdifaddr(const char *ifname, struct in_addr addr) 1245{ 1246 struct ifreq delreq; 1247 struct sockaddr_in *sa; 1248 1249 memset(&delreq, 0, sizeof(delreq)); 1250 strncpy(delreq.ifr_name, ifname, sizeof(delreq.ifr_name)); 1251 sa = (struct sockaddr_in *)(void *)&delreq.ifr_addr; 1252 sa->sin_family = AF_INET; 1253 sa->sin_len = sizeof(*sa); 1254 sa->sin_addr = addr; 1255 1256 return (ioctl(mib_netsock, SIOCDIFADDR, &delreq)); 1257} 1258 1259/* 1260 * Verify an interface address without fetching the entire list 1261 */ 1262static int 1263verify_ifa(const char *name, struct mibifa *ifa) 1264{ 1265 struct ifreq req; 1266 struct sockaddr_in *sa; 1267 1268 memset(&req, 0, sizeof(req)); 1269 strncpy(req.ifr_name, name, sizeof(req.ifr_name)); 1270 sa = (struct sockaddr_in *)(void *)&req.ifr_addr; 1271 sa->sin_family = AF_INET; 1272 sa->sin_len = sizeof(*sa); 1273 sa->sin_addr = ifa->inaddr; 1274 1275 if (ioctl(mib_netsock, SIOCGIFADDR, &req) == -1) 1276 return (-1); 1277 if (ifa->inaddr.s_addr != sa->sin_addr.s_addr) { 1278 syslog(LOG_ERR, "%s: address mismatch", __func__); 1279 return (-1); 1280 } 1281 1282 if (ioctl(mib_netsock, SIOCGIFNETMASK, &req) == -1) 1283 return (-1); 1284 if (ifa->inmask.s_addr != sa->sin_addr.s_addr) { 1285 syslog(LOG_ERR, "%s: netmask mismatch", __func__); 1286 return (-1); 1287 } 1288 return (0); 1289} 1290 1291/* 1292 * Restore a deleted interface address. Don't wait for the routing socket 1293 * to update us. 1294 */ 1295void 1296mib_undestroy_ifa(struct mibifa *ifa) 1297{ 1298 struct mibif *ifp; 1299 1300 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 1301 /* keep it destroyed */ 1302 return; 1303 1304 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) 1305 /* keep it destroyed */ 1306 return; 1307 1308 ifa->flags &= ~MIBIFA_DESTROYED; 1309} 1310 1311/* 1312 * Destroy an interface address 1313 */ 1314int 1315mib_destroy_ifa(struct mibifa *ifa) 1316{ 1317 struct mibif *ifp; 1318 1319 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1320 /* ups. */ 1321 mib_iflist_bad = 1; 1322 return (-1); 1323 } 1324 if (siocdifaddr(ifp->name, ifa->inaddr)) { 1325 /* ups. */ 1326 syslog(LOG_ERR, "SIOCDIFADDR: %m"); 1327 mib_iflist_bad = 1; 1328 return (-1); 1329 } 1330 ifa->flags |= MIBIFA_DESTROYED; 1331 return (0); 1332} 1333 1334/* 1335 * Rollback the modification of an address. Don't bother to wait for 1336 * the routing socket. 1337 */ 1338void 1339mib_unmodify_ifa(struct mibifa *ifa) 1340{ 1341 struct mibif *ifp; 1342 1343 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1344 /* ups. */ 1345 mib_iflist_bad = 1; 1346 return; 1347 } 1348 1349 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1350 /* ups. */ 1351 mib_iflist_bad = 1; 1352 return; 1353 } 1354} 1355 1356/* 1357 * Modify an IFA. 1358 */ 1359int 1360mib_modify_ifa(struct mibifa *ifa) 1361{ 1362 struct mibif *ifp; 1363 1364 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1365 /* ups. */ 1366 mib_iflist_bad = 1; 1367 return (-1); 1368 } 1369 1370 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1371 /* ups. */ 1372 mib_iflist_bad = 1; 1373 return (-1); 1374 } 1375 1376 if (verify_ifa(ifp->name, ifa)) { 1377 /* ups. */ 1378 mib_iflist_bad = 1; 1379 return (-1); 1380 } 1381 1382 return (0); 1383} 1384 1385/* 1386 * Destroy a freshly created interface address. Don't bother to wait for 1387 * the routing socket. 1388 */ 1389void 1390mib_uncreate_ifa(struct mibifa *ifa) 1391{ 1392 struct mibif *ifp; 1393 1394 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1395 /* ups. */ 1396 mib_iflist_bad = 1; 1397 return; 1398 } 1399 if (siocdifaddr(ifp->name, ifa->inaddr)) { 1400 /* ups. */ 1401 mib_iflist_bad = 1; 1402 return; 1403 } 1404 1405 destroy_ifa(ifa); 1406} 1407 1408/* 1409 * Create a new ifa and verify it 1410 */ 1411struct mibifa * 1412mib_create_ifa(u_int ifindex, struct in_addr addr, struct in_addr mask, 1413 struct in_addr bcast) 1414{ 1415 struct mibif *ifp; 1416 struct mibifa *ifa; 1417 1418 if ((ifp = mib_find_if(ifindex)) == NULL) 1419 return (NULL); 1420 if ((ifa = alloc_ifa(ifindex, addr)) == NULL) 1421 return (NULL); 1422 ifa->inmask = mask; 1423 ifa->inbcast = bcast; 1424 1425 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1426 syslog(LOG_ERR, "%s: %m", __func__); 1427 destroy_ifa(ifa); 1428 return (NULL); 1429 } 1430 if (verify_ifa(ifp->name, ifa)) { 1431 destroy_ifa(ifa); 1432 return (NULL); 1433 } 1434 return (ifa); 1435} 1436 1437/* 1438 * Get all cloning interfaces and make them dynamic. 1439 * Hah! Whe should probably do this on a periodic basis (XXX). 1440 */ 1441static void 1442get_cloners(void) 1443{ 1444 struct if_clonereq req; 1445 char *buf, *cp; 1446 int i; 1447 1448 memset(&req, 0, sizeof(req)); 1449 if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { 1450 syslog(LOG_ERR, "get cloners: %m"); 1451 return; 1452 } 1453 if ((buf = malloc(req.ifcr_total * IFNAMSIZ)) == NULL) { 1454 syslog(LOG_ERR, "%m"); 1455 return; 1456 } 1457 req.ifcr_count = req.ifcr_total; 1458 req.ifcr_buffer = buf; 1459 if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { 1460 syslog(LOG_ERR, "get cloners: %m"); 1461 free(buf); 1462 return; 1463 } 1464 for (cp = buf, i = 0; i < req.ifcr_total; i++, cp += IFNAMSIZ) 1465 mib_if_set_dyn(cp); 1466 free(buf); 1467} 1468 1469/* 1470 * Idle function 1471 */ 1472static void 1473mibII_idle(void) 1474{ 1475 struct mibifa *ifa; 1476 1477 if (mib_iflist_bad) { 1478 TAILQ_FOREACH(ifa, &mibifa_list, link) 1479 ifa->flags &= ~MIBIFA_DESTROYED; 1480 1481 /* assume, that all cloning interfaces are dynamic */ 1482 get_cloners(); 1483 1484 mib_refresh_iflist(); 1485 update_ifa_info(); 1486 mib_arp_update(); 1487 mib_iflist_bad = 0; 1488 } 1489 if (update_arp) 1490 mib_arp_update(); 1491} 1492 1493 1494/* 1495 * Start the module 1496 */ 1497static void 1498mibII_start(void) 1499{ 1500 if ((route_fd = fd_select(route, route_input, NULL, module)) == NULL) { 1501 syslog(LOG_ERR, "fd_select(route): %m"); 1502 return; 1503 } 1504 mib_refresh_iflist(); 1505 update_ifa_info(); 1506 mib_arp_update(); 1507 (void)mib_fetch_route(); 1508 mib_iftable_last_change = 0; 1509 mib_ifstack_last_change = 0; 1510 1511 ifmib_reg = or_register(&oid_ifMIB, 1512 "The MIB module to describe generic objects for network interface" 1513 " sub-layers.", module); 1514 1515 ipmib_reg = or_register(&oid_ipMIB, 1516 "The MIB module for managing IP and ICMP implementations, but " 1517 "excluding their management of IP routes.", module); 1518 1519 tcpmib_reg = or_register(&oid_tcpMIB, 1520 "The MIB module for managing TCP implementations.", module); 1521 1522 udpmib_reg = or_register(&oid_udpMIB, 1523 "The MIB module for managing UDP implementations.", module); 1524 1525 ipForward_reg = or_register(&oid_ipForward, 1526 "The MIB module for the display of CIDR multipath IP Routes.", 1527 module); 1528} 1529 1530/* 1531 * Initialize the module 1532 */ 1533static int 1534mibII_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 1535{ 1536 size_t len; 1537 1538 module = mod; 1539 1540 len = sizeof(clockinfo); 1541 if (sysctlbyname("kern.clockrate", &clockinfo, &len, NULL, 0) == -1) { 1542 syslog(LOG_ERR, "kern.clockrate: %m"); 1543 return (-1); 1544 } 1545 if (len != sizeof(clockinfo)) { 1546 syslog(LOG_ERR, "kern.clockrate: wrong size"); 1547 return (-1); 1548 } 1549 1550 if ((route = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1) { 1551 syslog(LOG_ERR, "PF_ROUTE: %m"); 1552 return (-1); 1553 } 1554 1555 if ((mib_netsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 1556 syslog(LOG_ERR, "PF_INET: %m"); 1557 (void)close(route); 1558 return (-1); 1559 } 1560 (void)shutdown(mib_netsock, SHUT_RDWR); 1561 1562 /* assume, that all cloning interfaces are dynamic */ 1563 get_cloners(); 1564 1565 return (0); 1566} 1567 1568static int 1569mibII_fini(void) 1570{ 1571 if (route_fd != NULL) 1572 fd_deselect(route_fd); 1573 if (route != -1) 1574 (void)close(route); 1575 if (mib_netsock != -1) 1576 (void)close(mib_netsock); 1577 /* XXX free memory */ 1578 1579 or_unregister(ipForward_reg); 1580 or_unregister(udpmib_reg); 1581 or_unregister(tcpmib_reg); 1582 or_unregister(ipmib_reg); 1583 or_unregister(ifmib_reg); 1584 1585 return (0); 1586} 1587 1588static void 1589mibII_loading(const struct lmodule *mod, int loaded) 1590{ 1591 struct mibif *ifp; 1592 1593 if (loaded == 1) 1594 return; 1595 1596 TAILQ_FOREACH(ifp, &mibif_list, link) 1597 if (ifp->xnotify_mod == mod) { 1598 ifp->xnotify_mod = NULL; 1599 ifp->xnotify_data = NULL; 1600 ifp->xnotify = NULL; 1601 } 1602 1603 mib_unregister_newif(mod); 1604} 1605 1606const struct snmp_module config = { 1607 "This module implements the interface and ip groups.", 1608 mibII_init, 1609 mibII_fini, 1610 mibII_idle, /* idle */ 1611 NULL, /* dump */ 1612 NULL, /* config */ 1613 mibII_start, 1614 NULL, 1615 mibII_ctree, 1616 mibII_CTREE_SIZE, 1617 mibII_loading 1618}; 1619 1620/* 1621 * Should have a list of these attached to each interface. 1622 */ 1623void * 1624mibif_notify(struct mibif *ifp, const struct lmodule *mod, 1625 mibif_notify_f func, void *data) 1626{ 1627 ifp->xnotify = func; 1628 ifp->xnotify_data = data; 1629 ifp->xnotify_mod = mod; 1630 1631 return (ifp); 1632} 1633 1634void 1635mibif_unnotify(void *arg) 1636{ 1637 struct mibif *ifp = arg; 1638 1639 ifp->xnotify = NULL; 1640 ifp->xnotify_data = NULL; 1641 ifp->xnotify_mod = NULL; 1642}
| 739 ifp->sysindex = sysindex; 740 strcpy(ifp->name, name); 741 strcpy(ifp->descr, name); 742 ifp->spec_oid = oid_zeroDotZero; 743 744 map = NULL; 745 if (!mib_if_is_dyn(ifp->name)) { 746 /* non-dynamic. look whether we know the interface */ 747 STAILQ_FOREACH(map, &mibindexmap_list, link) 748 if (strcmp(map->name, ifp->name) == 0) { 749 ifp->index = map->ifindex; 750 map->mibif = ifp; 751 break; 752 } 753 /* assume it has a connector if it is not dynamic */ 754 ifp->has_connector = 1; 755 ifp->trap_enable = 1; 756 } 757 if (map == NULL) { 758 /* new interface - get new index */ 759 if (next_if_index > 0x7fffffff) 760 errx(1, "ifindex wrap"); 761 762 if ((map = malloc(sizeof(*map))) == NULL) { 763 syslog(LOG_ERR, "ifmap: %m"); 764 free(ifp); 765 return (NULL); 766 } 767 map->ifindex = next_if_index++; 768 map->sysindex = ifp->sysindex; 769 strcpy(map->name, ifp->name); 770 map->mibif = ifp; 771 STAILQ_INSERT_TAIL(&mibindexmap_list, map, link); 772 } else { 773 /* re-instantiate. Introduce a counter discontinuity */ 774 ifp->counter_disc = get_ticks(); 775 } 776 ifp->index = map->ifindex; 777 ifp->mib.ifmd_data.ifi_link_state = LINK_STATE_UNKNOWN; 778 779 INSERT_OBJECT_INT(ifp, &mibif_list); 780 mib_if_number++; 781 mib_iftable_last_change = this_tick; 782 783 /* instantiate default ifStack entries */ 784 (void)mib_ifstack_create(ifp, NULL); 785 (void)mib_ifstack_create(NULL, ifp); 786 787 return (ifp); 788} 789 790/* 791 * Inform all interested parties about a new interface 792 */ 793static void 794notify_newif(struct mibif *ifp) 795{ 796 struct newifreg *reg; 797 798 TAILQ_FOREACH(reg, &newifreg_list, link) 799 if ((*reg->func)(ifp)) 800 return; 801} 802 803/* 804 * This is called for new interfaces after we have fetched the interface 805 * MIB. If this is a broadcast interface try to guess the broadcast address 806 * depending on the interface type. 807 */ 808static void 809check_llbcast(struct mibif *ifp) 810{ 811 static u_char ether_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 812 static u_char arcnet_bcast = 0; 813 struct mibrcvaddr *rcv; 814 815 if (!(ifp->mib.ifmd_flags & IFF_BROADCAST)) 816 return; 817 818 switch (ifp->mib.ifmd_data.ifi_type) { 819 820 case IFT_ETHER: 821 case IFT_FDDI: 822 case IFT_ISO88025: 823 if (mib_find_rcvaddr(ifp->index, ether_bcast, 6) == NULL && 824 (rcv = mib_rcvaddr_create(ifp, ether_bcast, 6)) != NULL) 825 rcv->flags |= MIBRCVADDR_BCAST; 826 break; 827 828 case IFT_ARCNET: 829 if (mib_find_rcvaddr(ifp->index, &arcnet_bcast, 1) == NULL && 830 (rcv = mib_rcvaddr_create(ifp, &arcnet_bcast, 1)) != NULL) 831 rcv->flags |= MIBRCVADDR_BCAST; 832 break; 833 } 834} 835 836 837/* 838 * Retrieve the current interface list from the system. 839 */ 840void 841mib_refresh_iflist(void) 842{ 843 struct mibif *ifp, *ifp1; 844 size_t len; 845 u_short idx; 846 int name[6]; 847 int count; 848 struct ifmibdata mib; 849 850 TAILQ_FOREACH(ifp, &mibif_list, link) 851 ifp->flags &= ~MIBIF_FOUND; 852 853 len = sizeof(count); 854 if (sysctlbyname("net.link.generic.system.ifcount", &count, &len, 855 NULL, 0) == -1) { 856 syslog(LOG_ERR, "ifcount: %m"); 857 return; 858 } 859 name[0] = CTL_NET; 860 name[1] = PF_LINK; 861 name[2] = NETLINK_GENERIC; 862 name[3] = IFMIB_IFDATA; 863 name[5] = IFDATA_GENERAL; 864 for (idx = 1; idx <= count; idx++) { 865 name[4] = idx; 866 len = sizeof(mib); 867 if (sysctl(name, 6, &mib, &len, NULL, 0) == -1) { 868 if (errno == ENOENT) 869 continue; 870 syslog(LOG_ERR, "ifmib(%u): %m", idx); 871 return; 872 } 873 if ((ifp = mib_find_if_sys(idx)) != NULL) { 874 ifp->flags |= MIBIF_FOUND; 875 continue; 876 } 877 /* Unknown interface - create */ 878 if ((ifp = mibif_create(idx, mib.ifmd_name)) != NULL) { 879 ifp->flags |= MIBIF_FOUND; 880 (void)mib_fetch_ifmib(ifp); 881 check_llbcast(ifp); 882 notify_newif(ifp); 883 } 884 } 885 886 /* 887 * Purge interfaces that disappeared 888 */ 889 ifp = TAILQ_FIRST(&mibif_list); 890 while (ifp != NULL) { 891 ifp1 = TAILQ_NEXT(ifp, link); 892 if (!(ifp->flags & MIBIF_FOUND)) 893 mibif_free(ifp); 894 ifp = ifp1; 895 } 896} 897 898/* 899 * Find an interface address 900 */ 901struct mibifa * 902mib_find_ifa(struct in_addr addr) 903{ 904 struct mibifa *ifa; 905 906 TAILQ_FOREACH(ifa, &mibifa_list, link) 907 if (ifa->inaddr.s_addr == addr.s_addr) 908 return (ifa); 909 return (NULL); 910} 911 912/* 913 * Process a new ARP entry 914 */ 915static void 916process_arp(const struct rt_msghdr *rtm, const struct sockaddr_dl *sdl, 917 const struct sockaddr_in *sa) 918{ 919 struct mibif *ifp; 920 struct mibarp *at; 921 922 /* IP arp table entry */ 923 if (sdl->sdl_alen == 0) { 924 update_arp = 1; 925 return; 926 } 927 if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) 928 return; 929 /* have a valid entry */ 930 if ((at = mib_find_arp(ifp, sa->sin_addr)) == NULL && 931 (at = mib_arp_create(ifp, sa->sin_addr, 932 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) 933 return; 934 935 if (rtm->rtm_rmx.rmx_expire == 0) 936 at->flags |= MIBARP_PERM; 937 else 938 at->flags &= ~MIBARP_PERM; 939 at->flags |= MIBARP_FOUND; 940} 941 942/* 943 * Handle a routing socket message. 944 */ 945static void 946handle_rtmsg(struct rt_msghdr *rtm) 947{ 948 struct sockaddr *addrs[RTAX_MAX]; 949 struct if_msghdr *ifm; 950 struct ifa_msghdr *ifam; 951 struct ifma_msghdr *ifmam; 952#ifdef RTM_IFANNOUNCE 953 struct if_announcemsghdr *ifan; 954#endif 955 struct mibif *ifp; 956 struct sockaddr_dl *sdl; 957 struct sockaddr_in *sa; 958 struct mibifa *ifa; 959 struct mibrcvaddr *rcv; 960 u_char *ptr; 961 962 if (rtm->rtm_version != RTM_VERSION) { 963 syslog(LOG_ERR, "Bogus RTM version %u", rtm->rtm_version); 964 return; 965 } 966 967 switch (rtm->rtm_type) { 968 969 case RTM_NEWADDR: 970 ifam = (struct ifa_msghdr *)rtm; 971 mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs); 972 if (addrs[RTAX_IFA] == NULL || addrs[RTAX_NETMASK] == NULL) 973 break; 974 975 sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; 976 if ((ifa = mib_find_ifa(sa->sin_addr)) == NULL) { 977 /* unknown address */ 978 if ((ifp = mib_find_if_sys(ifam->ifam_index)) == NULL) { 979 syslog(LOG_WARNING, "RTM_NEWADDR for unknown " 980 "interface %u", ifam->ifam_index); 981 break; 982 } 983 if ((ifa = alloc_ifa(ifp->index, sa->sin_addr)) == NULL) 984 break; 985 } 986 sa = (struct sockaddr_in *)(void *)addrs[RTAX_NETMASK]; 987 ifa->inmask = sa->sin_addr; 988 989 if (addrs[RTAX_BRD] != NULL) { 990 sa = (struct sockaddr_in *)(void *)addrs[RTAX_BRD]; 991 ifa->inbcast = sa->sin_addr; 992 } 993 ifa->flags |= MIBIFA_FOUND; 994 break; 995 996 case RTM_DELADDR: 997 ifam = (struct ifa_msghdr *)rtm; 998 mib_extract_addrs(ifam->ifam_addrs, (u_char *)(ifam + 1), addrs); 999 if (addrs[RTAX_IFA] == NULL) 1000 break; 1001 1002 sa = (struct sockaddr_in *)(void *)addrs[RTAX_IFA]; 1003 if ((ifa = mib_find_ifa(sa->sin_addr)) != NULL) { 1004 ifa->flags |= MIBIFA_FOUND; 1005 if (!(ifa->flags & MIBIFA_DESTROYED)) 1006 destroy_ifa(ifa); 1007 } 1008 break; 1009 1010 case RTM_NEWMADDR: 1011 ifmam = (struct ifma_msghdr *)rtm; 1012 mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); 1013 if (addrs[RTAX_IFA] == NULL || 1014 addrs[RTAX_IFA]->sa_family != AF_LINK) 1015 break; 1016 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; 1017 if ((rcv = mib_find_rcvaddr(sdl->sdl_index, 1018 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) { 1019 /* unknown address */ 1020 if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL) { 1021 syslog(LOG_WARNING, "RTM_NEWMADDR for unknown " 1022 "interface %u", sdl->sdl_index); 1023 break; 1024 } 1025 if ((rcv = mib_rcvaddr_create(ifp, 1026 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL) 1027 break; 1028 rcv->flags |= MIBRCVADDR_VOLATILE; 1029 } 1030 rcv->flags |= MIBRCVADDR_FOUND; 1031 break; 1032 1033 case RTM_DELMADDR: 1034 ifmam = (struct ifma_msghdr *)rtm; 1035 mib_extract_addrs(ifmam->ifmam_addrs, (u_char *)(ifmam + 1), addrs); 1036 if (addrs[RTAX_IFA] == NULL || 1037 addrs[RTAX_IFA]->sa_family != AF_LINK) 1038 break; 1039 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFA]; 1040 if ((rcv = mib_find_rcvaddr(sdl->sdl_index, 1041 sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) != NULL) 1042 mib_rcvaddr_delete(rcv); 1043 break; 1044 1045 case RTM_IFINFO: 1046 ifm = (struct if_msghdr *)rtm; 1047 mib_extract_addrs(ifm->ifm_addrs, (u_char *)(ifm + 1), addrs); 1048 if ((ifp = mib_find_if_sys(ifm->ifm_index)) == NULL) 1049 break; 1050 if (addrs[RTAX_IFP] != NULL && 1051 addrs[RTAX_IFP]->sa_family == AF_LINK) { 1052 sdl = (struct sockaddr_dl *)(void *)addrs[RTAX_IFP]; 1053 ptr = sdl->sdl_data + sdl->sdl_nlen; 1054 get_physaddr(ifp, sdl, ptr); 1055 } 1056 (void)mib_fetch_ifmib(ifp); 1057 break; 1058 1059#ifdef RTM_IFANNOUNCE 1060 case RTM_IFANNOUNCE: 1061 ifan = (struct if_announcemsghdr *)rtm; 1062 ifp = mib_find_if_sys(ifan->ifan_index); 1063 1064 switch (ifan->ifan_what) { 1065 1066 case IFAN_ARRIVAL: 1067 if (ifp == NULL && (ifp = mibif_create(ifan->ifan_index, 1068 ifan->ifan_name)) != NULL) { 1069 (void)mib_fetch_ifmib(ifp); 1070 check_llbcast(ifp); 1071 notify_newif(ifp); 1072 } 1073 break; 1074 1075 case IFAN_DEPARTURE: 1076 if (ifp != NULL) 1077 mibif_free(ifp); 1078 break; 1079 } 1080 break; 1081#endif 1082 1083 case RTM_GET: 1084 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 1085 if (rtm->rtm_flags & RTF_LLINFO) { 1086 if (addrs[RTAX_DST] == NULL || 1087 addrs[RTAX_GATEWAY] == NULL || 1088 addrs[RTAX_DST]->sa_family != AF_INET || 1089 addrs[RTAX_GATEWAY]->sa_family != AF_LINK) 1090 break; 1091 process_arp(rtm, 1092 (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY], 1093 (struct sockaddr_in *)(void *)addrs[RTAX_DST]); 1094 } else { 1095 if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) 1096 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 1097 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 1098 } 1099 break; 1100 1101 case RTM_ADD: 1102 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 1103 if (rtm->rtm_flags & RTF_LLINFO) { 1104 if (addrs[RTAX_DST] == NULL || 1105 addrs[RTAX_GATEWAY] == NULL || 1106 addrs[RTAX_DST]->sa_family != AF_INET || 1107 addrs[RTAX_GATEWAY]->sa_family != AF_LINK) 1108 break; 1109 process_arp(rtm, 1110 (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY], 1111 (struct sockaddr_in *)(void *)addrs[RTAX_DST]); 1112 } else { 1113 if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP)) 1114 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 1115 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 1116 } 1117 break; 1118 1119 case RTM_DELETE: 1120 mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs); 1121 if (rtm->rtm_errno == 0 && !(rtm->rtm_flags & RTF_LLINFO)) 1122 mib_sroute_process(rtm, addrs[RTAX_GATEWAY], 1123 addrs[RTAX_DST], addrs[RTAX_NETMASK]); 1124 break; 1125 } 1126} 1127 1128/* 1129 * send a routing message 1130 */ 1131void 1132mib_send_rtmsg(struct rt_msghdr *rtm, struct sockaddr *gw, 1133 struct sockaddr *dst, struct sockaddr *mask) 1134{ 1135 size_t len; 1136 struct rt_msghdr *msg; 1137 char *cp; 1138 ssize_t sent; 1139 1140 len = sizeof(*rtm) + SA_SIZE(gw) + SA_SIZE(dst) + SA_SIZE(mask); 1141 if ((msg = malloc(len)) == NULL) { 1142 syslog(LOG_ERR, "%s: %m", __func__); 1143 return; 1144 } 1145 cp = (char *)(msg + 1); 1146 1147 memset(msg, 0, sizeof(*msg)); 1148 msg->rtm_flags = 0; 1149 msg->rtm_version = RTM_VERSION; 1150 msg->rtm_addrs = RTA_DST | RTA_GATEWAY; 1151 1152 memcpy(cp, dst, SA_SIZE(dst)); 1153 cp += SA_SIZE(dst); 1154 memcpy(cp, gw, SA_SIZE(gw)); 1155 cp += SA_SIZE(gw); 1156 if (mask != NULL) { 1157 memcpy(cp, mask, SA_SIZE(mask)); 1158 cp += SA_SIZE(mask); 1159 msg->rtm_addrs |= RTA_NETMASK; 1160 } 1161 msg->rtm_msglen = cp - (char *)msg; 1162 msg->rtm_type = RTM_GET; 1163 if ((sent = write(route, msg, msg->rtm_msglen)) == -1) { 1164 syslog(LOG_ERR, "%s: write: %m", __func__); 1165 free(msg); 1166 return; 1167 } 1168 if (sent != msg->rtm_msglen) { 1169 syslog(LOG_ERR, "%s: short write", __func__); 1170 free(msg); 1171 return; 1172 } 1173 free(msg); 1174} 1175 1176/* 1177 * Fetch the routing table via sysctl 1178 */ 1179u_char * 1180mib_fetch_rtab(int af, int info, int arg, size_t *lenp) 1181{ 1182 int name[6]; 1183 u_char *buf, *newbuf; 1184 1185 name[0] = CTL_NET; 1186 name[1] = PF_ROUTE; 1187 name[2] = 0; 1188 name[3] = af; 1189 name[4] = info; 1190 name[5] = arg; 1191 1192 *lenp = 0; 1193 1194 /* initial estimate */ 1195 if (sysctl(name, 6, NULL, lenp, NULL, 0) == -1) { 1196 syslog(LOG_ERR, "sysctl estimate (%d,%d,%d,%d,%d,%d): %m", 1197 name[0], name[1], name[2], name[3], name[4], name[5]); 1198 return (NULL); 1199 } 1200 if (*lenp == 0) 1201 return (NULL); 1202 1203 buf = NULL; 1204 for (;;) { 1205 if ((newbuf = realloc(buf, *lenp)) == NULL) { 1206 syslog(LOG_ERR, "sysctl buffer: %m"); 1207 free(buf); 1208 return (NULL); 1209 } 1210 buf = newbuf; 1211 1212 if (sysctl(name, 6, buf, lenp, NULL, 0) == 0) 1213 break; 1214 1215 if (errno != ENOMEM) { 1216 syslog(LOG_ERR, "sysctl get: %m"); 1217 free(buf); 1218 return (NULL); 1219 } 1220 *lenp += *lenp / 8 + 1; 1221 } 1222 1223 return (buf); 1224} 1225 1226/* 1227 * Update the following info: interface, interface addresses, interface 1228 * receive addresses, arp-table. 1229 * This does not change the interface list itself. 1230 */ 1231static void 1232update_ifa_info(void) 1233{ 1234 u_char *buf, *next; 1235 struct rt_msghdr *rtm; 1236 struct mibifa *ifa, *ifa1; 1237 struct mibrcvaddr *rcv, *rcv1; 1238 size_t needed; 1239 static const int infos[][3] = { 1240 { 0, NET_RT_IFLIST, 0 }, 1241#ifdef NET_RT_IFMALIST 1242 { AF_LINK, NET_RT_IFMALIST, 0 }, 1243#endif 1244 }; 1245 u_int i; 1246 1247 TAILQ_FOREACH(ifa, &mibifa_list, link) 1248 ifa->flags &= ~MIBIFA_FOUND; 1249 TAILQ_FOREACH(rcv, &mibrcvaddr_list, link) 1250 rcv->flags &= ~MIBRCVADDR_FOUND; 1251 1252 for (i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { 1253 if ((buf = mib_fetch_rtab(infos[i][0], infos[i][1], infos[i][2], 1254 &needed)) == NULL) 1255 continue; 1256 1257 next = buf; 1258 while (next < buf + needed) { 1259 rtm = (struct rt_msghdr *)(void *)next; 1260 next += rtm->rtm_msglen; 1261 handle_rtmsg(rtm); 1262 } 1263 free(buf); 1264 } 1265 1266 /* 1267 * Purge the address list of unused entries. These may happen for 1268 * interface aliases that are on the same subnet. We don't receive 1269 * routing socket messages for them. 1270 */ 1271 ifa = TAILQ_FIRST(&mibifa_list); 1272 while (ifa != NULL) { 1273 ifa1 = TAILQ_NEXT(ifa, link); 1274 if (!(ifa->flags & MIBIFA_FOUND)) 1275 destroy_ifa(ifa); 1276 ifa = ifa1; 1277 } 1278 1279 rcv = TAILQ_FIRST(&mibrcvaddr_list); 1280 while (rcv != NULL) { 1281 rcv1 = TAILQ_NEXT(rcv, link); 1282 if (!(rcv->flags & (MIBRCVADDR_FOUND | MIBRCVADDR_BCAST | 1283 MIBRCVADDR_HW))) 1284 mib_rcvaddr_delete(rcv); 1285 rcv = rcv1; 1286 } 1287} 1288 1289/* 1290 * Update arp table 1291 */ 1292void 1293mib_arp_update(void) 1294{ 1295 struct mibarp *at, *at1; 1296 size_t needed; 1297 u_char *buf, *next; 1298 struct rt_msghdr *rtm; 1299 1300 if (in_update_arp) 1301 return; /* Aaargh */ 1302 in_update_arp = 1; 1303 1304 TAILQ_FOREACH(at, &mibarp_list, link) 1305 at->flags &= ~MIBARP_FOUND; 1306 1307 if ((buf = mib_fetch_rtab(AF_INET, NET_RT_FLAGS, RTF_LLINFO, &needed)) == NULL) { 1308 in_update_arp = 0; 1309 return; 1310 } 1311 1312 next = buf; 1313 while (next < buf + needed) { 1314 rtm = (struct rt_msghdr *)(void *)next; 1315 next += rtm->rtm_msglen; 1316 handle_rtmsg(rtm); 1317 } 1318 free(buf); 1319 1320 at = TAILQ_FIRST(&mibarp_list); 1321 while (at != NULL) { 1322 at1 = TAILQ_NEXT(at, link); 1323 if (!(at->flags & MIBARP_FOUND)) 1324 mib_arp_delete(at); 1325 at = at1; 1326 } 1327 mibarpticks = get_ticks(); 1328 update_arp = 0; 1329 in_update_arp = 0; 1330} 1331 1332 1333/* 1334 * Intput on the routing socket. 1335 */ 1336static void 1337route_input(int fd, void *udata __unused) 1338{ 1339 u_char buf[1024 * 16]; 1340 ssize_t n; 1341 struct rt_msghdr *rtm; 1342 1343 if ((n = read(fd, buf, sizeof(buf))) == -1) 1344 err(1, "read(rt_socket)"); 1345 1346 if (n == 0) 1347 errx(1, "EOF on rt_socket"); 1348 1349 rtm = (struct rt_msghdr *)(void *)buf; 1350 if ((size_t)n != rtm->rtm_msglen) 1351 errx(1, "n=%zu, rtm_msglen=%u", (size_t)n, rtm->rtm_msglen); 1352 1353 handle_rtmsg(rtm); 1354} 1355 1356/* 1357 * execute and SIOCAIFADDR 1358 */ 1359static int 1360siocaifaddr(char *ifname, struct in_addr addr, struct in_addr mask, 1361 struct in_addr bcast) 1362{ 1363 struct ifaliasreq addreq; 1364 struct sockaddr_in *sa; 1365 1366 memset(&addreq, 0, sizeof(addreq)); 1367 strncpy(addreq.ifra_name, ifname, sizeof(addreq.ifra_name)); 1368 1369 sa = (struct sockaddr_in *)(void *)&addreq.ifra_addr; 1370 sa->sin_family = AF_INET; 1371 sa->sin_len = sizeof(*sa); 1372 sa->sin_addr = addr; 1373 1374 sa = (struct sockaddr_in *)(void *)&addreq.ifra_mask; 1375 sa->sin_family = AF_INET; 1376 sa->sin_len = sizeof(*sa); 1377 sa->sin_addr = mask; 1378 1379 sa = (struct sockaddr_in *)(void *)&addreq.ifra_broadaddr; 1380 sa->sin_family = AF_INET; 1381 sa->sin_len = sizeof(*sa); 1382 sa->sin_addr = bcast; 1383 1384 return (ioctl(mib_netsock, SIOCAIFADDR, &addreq)); 1385} 1386 1387/* 1388 * Exececute a SIOCDIFADDR 1389 */ 1390static int 1391siocdifaddr(const char *ifname, struct in_addr addr) 1392{ 1393 struct ifreq delreq; 1394 struct sockaddr_in *sa; 1395 1396 memset(&delreq, 0, sizeof(delreq)); 1397 strncpy(delreq.ifr_name, ifname, sizeof(delreq.ifr_name)); 1398 sa = (struct sockaddr_in *)(void *)&delreq.ifr_addr; 1399 sa->sin_family = AF_INET; 1400 sa->sin_len = sizeof(*sa); 1401 sa->sin_addr = addr; 1402 1403 return (ioctl(mib_netsock, SIOCDIFADDR, &delreq)); 1404} 1405 1406/* 1407 * Verify an interface address without fetching the entire list 1408 */ 1409static int 1410verify_ifa(const char *name, struct mibifa *ifa) 1411{ 1412 struct ifreq req; 1413 struct sockaddr_in *sa; 1414 1415 memset(&req, 0, sizeof(req)); 1416 strncpy(req.ifr_name, name, sizeof(req.ifr_name)); 1417 sa = (struct sockaddr_in *)(void *)&req.ifr_addr; 1418 sa->sin_family = AF_INET; 1419 sa->sin_len = sizeof(*sa); 1420 sa->sin_addr = ifa->inaddr; 1421 1422 if (ioctl(mib_netsock, SIOCGIFADDR, &req) == -1) 1423 return (-1); 1424 if (ifa->inaddr.s_addr != sa->sin_addr.s_addr) { 1425 syslog(LOG_ERR, "%s: address mismatch", __func__); 1426 return (-1); 1427 } 1428 1429 if (ioctl(mib_netsock, SIOCGIFNETMASK, &req) == -1) 1430 return (-1); 1431 if (ifa->inmask.s_addr != sa->sin_addr.s_addr) { 1432 syslog(LOG_ERR, "%s: netmask mismatch", __func__); 1433 return (-1); 1434 } 1435 return (0); 1436} 1437 1438/* 1439 * Restore a deleted interface address. Don't wait for the routing socket 1440 * to update us. 1441 */ 1442void 1443mib_undestroy_ifa(struct mibifa *ifa) 1444{ 1445 struct mibif *ifp; 1446 1447 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) 1448 /* keep it destroyed */ 1449 return; 1450 1451 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) 1452 /* keep it destroyed */ 1453 return; 1454 1455 ifa->flags &= ~MIBIFA_DESTROYED; 1456} 1457 1458/* 1459 * Destroy an interface address 1460 */ 1461int 1462mib_destroy_ifa(struct mibifa *ifa) 1463{ 1464 struct mibif *ifp; 1465 1466 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1467 /* ups. */ 1468 mib_iflist_bad = 1; 1469 return (-1); 1470 } 1471 if (siocdifaddr(ifp->name, ifa->inaddr)) { 1472 /* ups. */ 1473 syslog(LOG_ERR, "SIOCDIFADDR: %m"); 1474 mib_iflist_bad = 1; 1475 return (-1); 1476 } 1477 ifa->flags |= MIBIFA_DESTROYED; 1478 return (0); 1479} 1480 1481/* 1482 * Rollback the modification of an address. Don't bother to wait for 1483 * the routing socket. 1484 */ 1485void 1486mib_unmodify_ifa(struct mibifa *ifa) 1487{ 1488 struct mibif *ifp; 1489 1490 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1491 /* ups. */ 1492 mib_iflist_bad = 1; 1493 return; 1494 } 1495 1496 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1497 /* ups. */ 1498 mib_iflist_bad = 1; 1499 return; 1500 } 1501} 1502 1503/* 1504 * Modify an IFA. 1505 */ 1506int 1507mib_modify_ifa(struct mibifa *ifa) 1508{ 1509 struct mibif *ifp; 1510 1511 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1512 /* ups. */ 1513 mib_iflist_bad = 1; 1514 return (-1); 1515 } 1516 1517 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1518 /* ups. */ 1519 mib_iflist_bad = 1; 1520 return (-1); 1521 } 1522 1523 if (verify_ifa(ifp->name, ifa)) { 1524 /* ups. */ 1525 mib_iflist_bad = 1; 1526 return (-1); 1527 } 1528 1529 return (0); 1530} 1531 1532/* 1533 * Destroy a freshly created interface address. Don't bother to wait for 1534 * the routing socket. 1535 */ 1536void 1537mib_uncreate_ifa(struct mibifa *ifa) 1538{ 1539 struct mibif *ifp; 1540 1541 if ((ifp = mib_find_if(ifa->ifindex)) == NULL) { 1542 /* ups. */ 1543 mib_iflist_bad = 1; 1544 return; 1545 } 1546 if (siocdifaddr(ifp->name, ifa->inaddr)) { 1547 /* ups. */ 1548 mib_iflist_bad = 1; 1549 return; 1550 } 1551 1552 destroy_ifa(ifa); 1553} 1554 1555/* 1556 * Create a new ifa and verify it 1557 */ 1558struct mibifa * 1559mib_create_ifa(u_int ifindex, struct in_addr addr, struct in_addr mask, 1560 struct in_addr bcast) 1561{ 1562 struct mibif *ifp; 1563 struct mibifa *ifa; 1564 1565 if ((ifp = mib_find_if(ifindex)) == NULL) 1566 return (NULL); 1567 if ((ifa = alloc_ifa(ifindex, addr)) == NULL) 1568 return (NULL); 1569 ifa->inmask = mask; 1570 ifa->inbcast = bcast; 1571 1572 if (siocaifaddr(ifp->name, ifa->inaddr, ifa->inmask, ifa->inbcast)) { 1573 syslog(LOG_ERR, "%s: %m", __func__); 1574 destroy_ifa(ifa); 1575 return (NULL); 1576 } 1577 if (verify_ifa(ifp->name, ifa)) { 1578 destroy_ifa(ifa); 1579 return (NULL); 1580 } 1581 return (ifa); 1582} 1583 1584/* 1585 * Get all cloning interfaces and make them dynamic. 1586 * Hah! Whe should probably do this on a periodic basis (XXX). 1587 */ 1588static void 1589get_cloners(void) 1590{ 1591 struct if_clonereq req; 1592 char *buf, *cp; 1593 int i; 1594 1595 memset(&req, 0, sizeof(req)); 1596 if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { 1597 syslog(LOG_ERR, "get cloners: %m"); 1598 return; 1599 } 1600 if ((buf = malloc(req.ifcr_total * IFNAMSIZ)) == NULL) { 1601 syslog(LOG_ERR, "%m"); 1602 return; 1603 } 1604 req.ifcr_count = req.ifcr_total; 1605 req.ifcr_buffer = buf; 1606 if (ioctl(mib_netsock, SIOCIFGCLONERS, &req) == -1) { 1607 syslog(LOG_ERR, "get cloners: %m"); 1608 free(buf); 1609 return; 1610 } 1611 for (cp = buf, i = 0; i < req.ifcr_total; i++, cp += IFNAMSIZ) 1612 mib_if_set_dyn(cp); 1613 free(buf); 1614} 1615 1616/* 1617 * Idle function 1618 */ 1619static void 1620mibII_idle(void) 1621{ 1622 struct mibifa *ifa; 1623 1624 if (mib_iflist_bad) { 1625 TAILQ_FOREACH(ifa, &mibifa_list, link) 1626 ifa->flags &= ~MIBIFA_DESTROYED; 1627 1628 /* assume, that all cloning interfaces are dynamic */ 1629 get_cloners(); 1630 1631 mib_refresh_iflist(); 1632 update_ifa_info(); 1633 mib_arp_update(); 1634 mib_iflist_bad = 0; 1635 } 1636 if (update_arp) 1637 mib_arp_update(); 1638} 1639 1640 1641/* 1642 * Start the module 1643 */ 1644static void 1645mibII_start(void) 1646{ 1647 if ((route_fd = fd_select(route, route_input, NULL, module)) == NULL) { 1648 syslog(LOG_ERR, "fd_select(route): %m"); 1649 return; 1650 } 1651 mib_refresh_iflist(); 1652 update_ifa_info(); 1653 mib_arp_update(); 1654 (void)mib_fetch_route(); 1655 mib_iftable_last_change = 0; 1656 mib_ifstack_last_change = 0; 1657 1658 ifmib_reg = or_register(&oid_ifMIB, 1659 "The MIB module to describe generic objects for network interface" 1660 " sub-layers.", module); 1661 1662 ipmib_reg = or_register(&oid_ipMIB, 1663 "The MIB module for managing IP and ICMP implementations, but " 1664 "excluding their management of IP routes.", module); 1665 1666 tcpmib_reg = or_register(&oid_tcpMIB, 1667 "The MIB module for managing TCP implementations.", module); 1668 1669 udpmib_reg = or_register(&oid_udpMIB, 1670 "The MIB module for managing UDP implementations.", module); 1671 1672 ipForward_reg = or_register(&oid_ipForward, 1673 "The MIB module for the display of CIDR multipath IP Routes.", 1674 module); 1675} 1676 1677/* 1678 * Initialize the module 1679 */ 1680static int 1681mibII_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 1682{ 1683 size_t len; 1684 1685 module = mod; 1686 1687 len = sizeof(clockinfo); 1688 if (sysctlbyname("kern.clockrate", &clockinfo, &len, NULL, 0) == -1) { 1689 syslog(LOG_ERR, "kern.clockrate: %m"); 1690 return (-1); 1691 } 1692 if (len != sizeof(clockinfo)) { 1693 syslog(LOG_ERR, "kern.clockrate: wrong size"); 1694 return (-1); 1695 } 1696 1697 if ((route = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1) { 1698 syslog(LOG_ERR, "PF_ROUTE: %m"); 1699 return (-1); 1700 } 1701 1702 if ((mib_netsock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 1703 syslog(LOG_ERR, "PF_INET: %m"); 1704 (void)close(route); 1705 return (-1); 1706 } 1707 (void)shutdown(mib_netsock, SHUT_RDWR); 1708 1709 /* assume, that all cloning interfaces are dynamic */ 1710 get_cloners(); 1711 1712 return (0); 1713} 1714 1715static int 1716mibII_fini(void) 1717{ 1718 if (route_fd != NULL) 1719 fd_deselect(route_fd); 1720 if (route != -1) 1721 (void)close(route); 1722 if (mib_netsock != -1) 1723 (void)close(mib_netsock); 1724 /* XXX free memory */ 1725 1726 or_unregister(ipForward_reg); 1727 or_unregister(udpmib_reg); 1728 or_unregister(tcpmib_reg); 1729 or_unregister(ipmib_reg); 1730 or_unregister(ifmib_reg); 1731 1732 return (0); 1733} 1734 1735static void 1736mibII_loading(const struct lmodule *mod, int loaded) 1737{ 1738 struct mibif *ifp; 1739 1740 if (loaded == 1) 1741 return; 1742 1743 TAILQ_FOREACH(ifp, &mibif_list, link) 1744 if (ifp->xnotify_mod == mod) { 1745 ifp->xnotify_mod = NULL; 1746 ifp->xnotify_data = NULL; 1747 ifp->xnotify = NULL; 1748 } 1749 1750 mib_unregister_newif(mod); 1751} 1752 1753const struct snmp_module config = { 1754 "This module implements the interface and ip groups.", 1755 mibII_init, 1756 mibII_fini, 1757 mibII_idle, /* idle */ 1758 NULL, /* dump */ 1759 NULL, /* config */ 1760 mibII_start, 1761 NULL, 1762 mibII_ctree, 1763 mibII_CTREE_SIZE, 1764 mibII_loading 1765}; 1766 1767/* 1768 * Should have a list of these attached to each interface. 1769 */ 1770void * 1771mibif_notify(struct mibif *ifp, const struct lmodule *mod, 1772 mibif_notify_f func, void *data) 1773{ 1774 ifp->xnotify = func; 1775 ifp->xnotify_data = data; 1776 ifp->xnotify_mod = mod; 1777 1778 return (ifp); 1779} 1780 1781void 1782mibif_unnotify(void *arg) 1783{ 1784 struct mibif *ifp = arg; 1785 1786 ifp->xnotify = NULL; 1787 ifp->xnotify_data = NULL; 1788 ifp->xnotify_mod = NULL; 1789}
|