| 828 | } |
| 829 | |
| 830 | void |
| 831 | pf_altq_ifnet_event(struct ifnet *ifp, int remove) |
| 832 | { |
| 833 | struct pf_altq *a1, *a2, *a3; |
| 834 | u_int32_t ticket; |
| 835 | int error = 0; |
| 836 | |
| 837 | /* |
| 838 | * No need to re-evaluate the configuration for events on interfaces |
| 839 | * that do not support ALTQ, as it's not possible for such |
| 840 | * interfaces to be part of the configuration. |
| 841 | */ |
| 842 | if (!ALTQ_IS_READY(&ifp->if_snd)) |
| 843 | return; |
| 844 | |
| 845 | /* Interrupt userland queue modifications */ |
| 846 | if (V_altqs_inactive_open) |
| 847 | pf_rollback_altq(V_ticket_altqs_inactive); |
| 848 | |
| 849 | /* Start new altq ruleset */ |
| 850 | if (pf_begin_altq(&ticket)) |
| 851 | return; |
| 852 | |
| 853 | /* Copy the current active set */ |
| 854 | TAILQ_FOREACH(a1, V_pf_altq_ifs_active, entries) { |
| 855 | a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT); |
| 856 | if (a2 == NULL) { |
| 857 | error = ENOMEM; |
| 858 | break; |
| 859 | } |
| 860 | bcopy(a1, a2, sizeof(struct pf_altq)); |
| 861 | |
| 862 | error = pf_altq_ifnet_event_add(ifp, remove, ticket, a2); |
| 863 | if (error) |
| 864 | break; |
| 865 | |
| 866 | TAILQ_INSERT_TAIL(V_pf_altq_ifs_inactive, a2, entries); |
| 867 | } |
| 868 | if (error) |
| 869 | goto out; |
| 870 | TAILQ_FOREACH(a1, V_pf_altqs_active, entries) { |
| 871 | a2 = malloc(sizeof(*a2), M_PFALTQ, M_NOWAIT); |
| 872 | if (a2 == NULL) { |
| 873 | error = ENOMEM; |
| 874 | break; |
| 875 | } |
| 876 | bcopy(a1, a2, sizeof(struct pf_altq)); |
| 877 | |
| 878 | if ((a2->qid = pf_qname2qid(a2->qname)) == 0) { |
| 879 | error = EBUSY; |
| 880 | free(a2, M_PFALTQ); |
| 881 | break; |
| 882 | } |
| 883 | a2->altq_disc = NULL; |
| 884 | TAILQ_FOREACH(a3, V_pf_altq_ifs_inactive, entries) { |
| 885 | if (strncmp(a3->ifname, a2->ifname, |
| 886 | IFNAMSIZ) == 0) { |
| 887 | a2->altq_disc = a3->altq_disc; |
no test coverage detected