* Returns true if an interface should be listed because any its groups * matches shell pattern "match" and none of groups matches pattern "nomatch". * If any pattern is NULL, corresponding condition is skipped. */
| 787 | * If any pattern is NULL, corresponding condition is skipped. |
| 788 | */ |
| 789 | static bool |
| 790 | group_member(const char *ifname, const char *match, const char *nomatch) |
| 791 | { |
| 792 | static int sock = -1; |
| 793 | |
| 794 | struct ifgroupreq ifgr; |
| 795 | struct ifg_req *ifg; |
| 796 | int len; |
| 797 | bool matched, nomatched; |
| 798 | |
| 799 | /* Sanity checks. */ |
| 800 | if (match == NULL && nomatch == NULL) |
| 801 | return (true); |
| 802 | if (ifname == NULL) |
| 803 | return (false); |
| 804 | |
| 805 | memset(&ifgr, 0, sizeof(ifgr)); |
| 806 | strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); |
| 807 | |
| 808 | /* The socket is opened once. Let _exit() close it. */ |
| 809 | if (sock == -1) { |
| 810 | sock = socket(AF_LOCAL, SOCK_DGRAM, 0); |
| 811 | if (sock == -1) |
| 812 | errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__); |
| 813 | } |
| 814 | |
| 815 | /* Determine amount of memory for the list of groups. */ |
| 816 | if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { |
| 817 | if (errno == EINVAL || errno == ENOTTY) |
| 818 | return (false); |
| 819 | else |
| 820 | errx(1, "%s: SIOCGIFGROUP", __func__); |
| 821 | } |
| 822 | |
| 823 | /* Obtain the list of groups. */ |
| 824 | len = ifgr.ifgr_len; |
| 825 | ifgr.ifgr_groups = |
| 826 | (struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg)); |
| 827 | |
| 828 | if (ifgr.ifgr_groups == NULL) |
| 829 | errx(1, "%s: no memory", __func__); |
| 830 | #ifndef FSTACK |
| 831 | if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) |
| 832 | #else |
| 833 | size_t offset = (char *)&(ifgr.ifgr_groups) - (char *)&(ifgr); |
| 834 | size_t clen = len; |
| 835 | if (ioctl_va(sock, SIOCGIFGROUP, (caddr_t)&ifgr, 3, offset, ifgr.ifgr_groups, clen) == -1) |
| 836 | #endif |
| 837 | errx(1, "%s: SIOCGIFGROUP", __func__); |
| 838 | |
| 839 | /* Perform matching. */ |
| 840 | matched = false; |
| 841 | nomatched = true; |
| 842 | for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) { |
| 843 | len -= sizeof(struct ifg_req); |
| 844 | if (match) |
| 845 | matched |= !fnmatch(match, ifg->ifgrq_group, 0); |
| 846 | if (nomatch) |