* The code common to handling reference counted flags, * e.g., in ifpromisc() and if_allmulti(). * The "pflag" argument can specify a permanent mode flag to check, * such as IFF_PPROMISC for promiscuous mode; should be 0 if none. * * Only to be used on stack-owned flags, not driver-owned flags. */
| 3103 | * Only to be used on stack-owned flags, not driver-owned flags. |
| 3104 | */ |
| 3105 | static int |
| 3106 | if_setflag(struct ifnet *ifp, int flag, int pflag, int *refcount, int onswitch) |
| 3107 | { |
| 3108 | struct ifreq ifr; |
| 3109 | int error; |
| 3110 | int oldflags, oldcount; |
| 3111 | |
| 3112 | /* Sanity checks to catch programming errors */ |
| 3113 | KASSERT((flag & (IFF_DRV_OACTIVE|IFF_DRV_RUNNING)) == 0, |
| 3114 | ("%s: setting driver-owned flag %d", __func__, flag)); |
| 3115 | |
| 3116 | if (onswitch) |
| 3117 | KASSERT(*refcount >= 0, |
| 3118 | ("%s: increment negative refcount %d for flag %d", |
| 3119 | __func__, *refcount, flag)); |
| 3120 | else |
| 3121 | KASSERT(*refcount > 0, |
| 3122 | ("%s: decrement non-positive refcount %d for flag %d", |
| 3123 | __func__, *refcount, flag)); |
| 3124 | |
| 3125 | /* In case this mode is permanent, just touch refcount */ |
| 3126 | if (ifp->if_flags & pflag) { |
| 3127 | *refcount += onswitch ? 1 : -1; |
| 3128 | return (0); |
| 3129 | } |
| 3130 | |
| 3131 | /* Save ifnet parameters for if_ioctl() may fail */ |
| 3132 | oldcount = *refcount; |
| 3133 | oldflags = ifp->if_flags; |
| 3134 | |
| 3135 | /* |
| 3136 | * See if we aren't the only and touching refcount is enough. |
| 3137 | * Actually toggle interface flag if we are the first or last. |
| 3138 | */ |
| 3139 | if (onswitch) { |
| 3140 | if ((*refcount)++) |
| 3141 | return (0); |
| 3142 | ifp->if_flags |= flag; |
| 3143 | } else { |
| 3144 | if (--(*refcount)) |
| 3145 | return (0); |
| 3146 | ifp->if_flags &= ~flag; |
| 3147 | } |
| 3148 | |
| 3149 | /* Call down the driver since we've changed interface flags */ |
| 3150 | if (ifp->if_ioctl == NULL) { |
| 3151 | error = EOPNOTSUPP; |
| 3152 | goto recover; |
| 3153 | } |
| 3154 | ifr.ifr_flags = ifp->if_flags & 0xffff; |
| 3155 | ifr.ifr_flagshigh = ifp->if_flags >> 16; |
| 3156 | error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); |
| 3157 | if (error) |
| 3158 | goto recover; |
| 3159 | /* Notify userland that interface flags have changed */ |
| 3160 | rt_ifmsg(ifp); |
| 3161 | return (0); |
| 3162 |
no test coverage detected