1100894Srwatson/*- 2189503Srwatson * Copyright (c) 1999-2002, 2009 Robert N. M. Watson 3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4126262Srwatson * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 5172930Srwatson * Copyright (c) 2006 SPARTA, Inc. 6182063Srwatson * Copyright (c) 2008 Apple Inc. 7100894Srwatson * All rights reserved. 8100894Srwatson * 9100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the 10100894Srwatson * TrustedBSD Project. 11100894Srwatson * 12172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract 13172930Srwatson * N66001-04-C-6019 ("SEFOS"). 14172930Srwatson * 15106392Srwatson * This software was developed for the FreeBSD Project in part by Network 16106392Srwatson * Associates Laboratories, the Security Research Division of Network 17106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 18106392Srwatson * as part of the DARPA CHATS research program. 19100894Srwatson * 20189503Srwatson * This software was developed at the University of Cambridge Computer 21189503Srwatson * Laboratory with support from a grant from Google, Inc. 22189503Srwatson * 23100894Srwatson * Redistribution and use in source and binary forms, with or without 24100894Srwatson * modification, are permitted provided that the following conditions 25100894Srwatson * are met: 26100894Srwatson * 1. Redistributions of source code must retain the above copyright 27100894Srwatson * notice, this list of conditions and the following disclaimer. 28100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright 29100894Srwatson * notice, this list of conditions and the following disclaimer in the 30100894Srwatson * documentation and/or other materials provided with the distribution. 31100894Srwatson * 32100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35100894Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42100894Srwatson * SUCH DAMAGE. 43100894Srwatson */ 44116182Sobrien 45116182Sobrien#include <sys/cdefs.h> 46116182Sobrien__FBSDID("$FreeBSD$"); 47116182Sobrien 48189503Srwatson#include "opt_kdtrace.h" 49100894Srwatson#include "opt_mac.h" 50101173Srwatson 51100894Srwatson#include <sys/param.h> 52100979Srwatson#include <sys/kernel.h> 53100979Srwatson#include <sys/lock.h> 54102949Sbde#include <sys/malloc.h> 55100979Srwatson#include <sys/mutex.h> 56100979Srwatson#include <sys/mac.h> 57164033Srwatson#include <sys/priv.h> 58116701Srwatson#include <sys/sbuf.h> 59189503Srwatson#include <sys/sdt.h> 60100979Srwatson#include <sys/systm.h> 61100979Srwatson#include <sys/mount.h> 62100979Srwatson#include <sys/file.h> 63100979Srwatson#include <sys/namei.h> 64122875Srwatson#include <sys/protosw.h> 65100979Srwatson#include <sys/socket.h> 66100979Srwatson#include <sys/socketvar.h> 67100979Srwatson#include <sys/sysctl.h> 68100894Srwatson 69100979Srwatson#include <net/bpfdesc.h> 70100979Srwatson#include <net/if.h> 71100979Srwatson#include <net/if_var.h> 72100979Srwatson 73163606Srwatson#include <security/mac/mac_framework.h> 74121357Srwatson#include <security/mac/mac_internal.h> 75165469Srwatson#include <security/mac/mac_policy.h> 76100979Srwatson 77126262Srwatson/* 78165423Srwatson * XXXRW: struct ifnet locking is incomplete in the network code, so we use 79165423Srwatson * our own global mutex for struct ifnet. Non-ideal, but should help in the 80165423Srwatson * SMP environment. 81131025Srwatson */ 82173095Srwatsonstruct mtx mac_ifnet_mtx; 83131025SrwatsonMTX_SYSINIT(mac_ifnet_mtx, &mac_ifnet_mtx, "mac_ifnet", MTX_DEF); 84131025Srwatson 85165423Srwatson/* 86165423Srwatson * Retrieve the label associated with an mbuf by searching for the tag. 87165423Srwatson * Depending on the value of mac_labelmbufs, it's possible that a label will 88165423Srwatson * not be present, in which case NULL is returned. Policies must handle the 89165423Srwatson * possibility of an mbuf not having label storage if they do not enforce 90165423Srwatson * early loading. 91165423Srwatson */ 92126262Srwatsonstruct label * 93168955Srwatsonmac_mbuf_to_label(struct mbuf *m) 94113482Srwatson{ 95113487Srwatson struct m_tag *tag; 96113482Srwatson struct label *label; 97113482Srwatson 98168955Srwatson if (m == NULL) 99128902Srwatson return (NULL); 100168955Srwatson tag = m_tag_find(m, PACKET_TAG_MACLABEL, NULL); 101128902Srwatson if (tag == NULL) 102128902Srwatson return (NULL); 103113487Srwatson label = (struct label *)(tag+1); 104113482Srwatson return (label); 105113482Srwatson} 106113482Srwatson 107122524Srwatsonstatic struct label * 108122524Srwatsonmac_bpfdesc_label_alloc(void) 109122524Srwatson{ 110122524Srwatson struct label *label; 111122524Srwatson 112122524Srwatson label = mac_labelzone_alloc(M_WAITOK); 113191731Srwatson MAC_POLICY_PERFORM(bpfdesc_init_label, label); 114122524Srwatson return (label); 115122524Srwatson} 116122524Srwatson 117100979Srwatsonvoid 118172930Srwatsonmac_bpfdesc_init(struct bpf_d *d) 119104521Srwatson{ 120104521Srwatson 121182063Srwatson if (mac_labeled & MPC_OBJECT_BPFDESC) 122182063Srwatson d->bd_label = mac_bpfdesc_label_alloc(); 123182063Srwatson else 124182063Srwatson d->bd_label = NULL; 125104521Srwatson} 126104521Srwatson 127122524Srwatsonstatic struct label * 128122524Srwatsonmac_ifnet_label_alloc(void) 129104521Srwatson{ 130122524Srwatson struct label *label; 131104521Srwatson 132122524Srwatson label = mac_labelzone_alloc(M_WAITOK); 133191731Srwatson MAC_POLICY_PERFORM(ifnet_init_label, label); 134122524Srwatson return (label); 135104521Srwatson} 136104521Srwatson 137104521Srwatsonvoid 138172930Srwatsonmac_ifnet_init(struct ifnet *ifp) 139105694Srwatson{ 140105694Srwatson 141182063Srwatson if (mac_labeled & MPC_OBJECT_IFNET) 142182063Srwatson ifp->if_label = mac_ifnet_label_alloc(); 143182063Srwatson else 144182063Srwatson ifp->if_label = NULL; 145105694Srwatson} 146105694Srwatson 147122875Srwatsonint 148172930Srwatsonmac_mbuf_tag_init(struct m_tag *tag, int flag) 149104527Srwatson{ 150113487Srwatson struct label *label; 151113526Srwatson int error; 152104528Srwatson 153113487Srwatson label = (struct label *) (tag + 1); 154113487Srwatson mac_init_label(label); 155104527Srwatson 156189797Srwatson if (flag & M_WAITOK) 157191731Srwatson MAC_POLICY_CHECK(mbuf_init_label, label, flag); 158189797Srwatson else 159191731Srwatson MAC_POLICY_CHECK_NOSLEEP(mbuf_init_label, label, flag); 160104528Srwatson if (error) { 161191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label); 162113487Srwatson mac_destroy_label(label); 163104528Srwatson } 164104528Srwatson return (error); 165104527Srwatson} 166104527Srwatson 167113487Srwatsonint 168172930Srwatsonmac_mbuf_init(struct mbuf *m, int flag) 169113487Srwatson{ 170113487Srwatson struct m_tag *tag; 171113487Srwatson int error; 172113487Srwatson 173113487Srwatson M_ASSERTPKTHDR(m); 174113487Srwatson 175182063Srwatson if (mac_labeled & MPC_OBJECT_MBUF) { 176182063Srwatson tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label), 177182063Srwatson flag); 178182063Srwatson if (tag == NULL) 179182063Srwatson return (ENOMEM); 180182063Srwatson error = mac_mbuf_tag_init(tag, flag); 181182063Srwatson if (error) { 182182063Srwatson m_tag_free(tag); 183182063Srwatson return (error); 184182063Srwatson } 185182063Srwatson m_tag_prepend(m, tag); 186113487Srwatson } 187113487Srwatson return (0); 188113487Srwatson} 189113487Srwatson 190122524Srwatsonstatic void 191122524Srwatsonmac_bpfdesc_label_free(struct label *label) 192122524Srwatson{ 193104541Srwatson 194191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_destroy_label, label); 195122524Srwatson mac_labelzone_free(label); 196104541Srwatson} 197104541Srwatson 198105988Srwatsonvoid 199172930Srwatsonmac_bpfdesc_destroy(struct bpf_d *d) 200104521Srwatson{ 201104521Srwatson 202182063Srwatson if (d->bd_label != NULL) { 203182063Srwatson mac_bpfdesc_label_free(d->bd_label); 204182063Srwatson d->bd_label = NULL; 205182063Srwatson } 206104521Srwatson} 207104521Srwatson 208105694Srwatsonstatic void 209122524Srwatsonmac_ifnet_label_free(struct label *label) 210104521Srwatson{ 211104521Srwatson 212191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ifnet_destroy_label, label); 213122524Srwatson mac_labelzone_free(label); 214104521Srwatson} 215104521Srwatson 216104521Srwatsonvoid 217172930Srwatsonmac_ifnet_destroy(struct ifnet *ifp) 218105694Srwatson{ 219105694Srwatson 220182063Srwatson if (ifp->if_label != NULL) { 221182063Srwatson mac_ifnet_label_free(ifp->if_label); 222182063Srwatson ifp->if_label = NULL; 223182063Srwatson } 224105694Srwatson} 225105694Srwatson 226122875Srwatsonvoid 227172930Srwatsonmac_mbuf_tag_destroy(struct m_tag *tag) 228104521Srwatson{ 229113487Srwatson struct label *label; 230104521Srwatson 231113487Srwatson label = (struct label *)(tag+1); 232113487Srwatson 233191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(mbuf_destroy_label, label); 234113487Srwatson mac_destroy_label(label); 235104521Srwatson} 236104521Srwatson 237165423Srwatson/* 238172930Srwatson * mac_mbuf_tag_copy is called when an mbuf header is duplicated, in which 239165423Srwatson * case the labels must also be duplicated. 240165423Srwatson */ 241122820Srwatsonvoid 242172930Srwatsonmac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest) 243113487Srwatson{ 244113487Srwatson struct label *src_label, *dest_label; 245113487Srwatson 246113487Srwatson src_label = (struct label *)(src+1); 247113487Srwatson dest_label = (struct label *)(dest+1); 248113487Srwatson 249113487Srwatson /* 250172930Srwatson * mac_mbuf_tag_init() is called on the target tag in m_tag_copy(), 251165423Srwatson * so we don't need to call it here. 252113487Srwatson */ 253191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label); 254113487Srwatson} 255113487Srwatson 256147785Srwatsonvoid 257172930Srwatsonmac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to) 258147785Srwatson{ 259147785Srwatson struct label *src_label, *dest_label; 260147785Srwatson 261193393Srwatson if (mac_policy_count == 0) 262193393Srwatson return; 263193393Srwatson 264147785Srwatson src_label = mac_mbuf_to_label(m_from); 265147785Srwatson dest_label = mac_mbuf_to_label(m_to); 266147785Srwatson 267191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label); 268147785Srwatson} 269147785Srwatson 270131025Srwatsonstatic void 271172930Srwatsonmac_ifnet_copy_label(struct label *src, struct label *dest) 272131025Srwatson{ 273131025Srwatson 274191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ifnet_copy_label, src, dest); 275131025Srwatson} 276131025Srwatson 277104522Srwatsonstatic int 278172930Srwatsonmac_ifnet_externalize_label(struct label *label, char *elements, 279122159Srwatson char *outbuf, size_t outbuflen) 280104522Srwatson{ 281104522Srwatson int error; 282104522Srwatson 283191731Srwatson MAC_POLICY_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen); 284104522Srwatson 285104522Srwatson return (error); 286104522Srwatson} 287104522Srwatson 288105694Srwatsonstatic int 289172930Srwatsonmac_ifnet_internalize_label(struct label *label, char *string) 290105694Srwatson{ 291105694Srwatson int error; 292105694Srwatson 293191731Srwatson MAC_POLICY_INTERNALIZE(ifnet, label, string); 294105694Srwatson 295105694Srwatson return (error); 296105694Srwatson} 297105694Srwatson 298104521Srwatsonvoid 299172930Srwatsonmac_ifnet_create(struct ifnet *ifp) 300100979Srwatson{ 301100979Srwatson 302193391Srwatson if (mac_policy_count == 0) 303193391Srwatson return; 304193391Srwatson 305168955Srwatson MAC_IFNET_LOCK(ifp); 306191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label); 307168955Srwatson MAC_IFNET_UNLOCK(ifp); 308100979Srwatson} 309100979Srwatson 310100979Srwatsonvoid 311172930Srwatsonmac_bpfdesc_create(struct ucred *cred, struct bpf_d *d) 312100979Srwatson{ 313100979Srwatson 314191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label); 315100979Srwatson} 316100979Srwatson 317100979Srwatsonvoid 318172930Srwatsonmac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m) 319100979Srwatson{ 320113482Srwatson struct label *label; 321100979Srwatson 322247629Smelifaro /* Assume reader lock is enough. */ 323168955Srwatson BPFD_LOCK_ASSERT(d); 324126406Srwatson 325193391Srwatson if (mac_policy_count == 0) 326193391Srwatson return; 327193391Srwatson 328168955Srwatson label = mac_mbuf_to_label(m); 329113482Srwatson 330191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m, 331191731Srwatson label); 332100979Srwatson} 333100979Srwatson 334100979Srwatsonvoid 335172930Srwatsonmac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m) 336100979Srwatson{ 337113482Srwatson struct label *label; 338100979Srwatson 339193391Srwatson if (mac_policy_count == 0) 340193391Srwatson return; 341193391Srwatson 342168955Srwatson label = mac_mbuf_to_label(m); 343113482Srwatson 344168955Srwatson MAC_IFNET_LOCK(ifp); 345191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, ifp->if_label, m, 346191731Srwatson label); 347168955Srwatson MAC_IFNET_UNLOCK(ifp); 348100979Srwatson} 349100979Srwatson 350189503SrwatsonMAC_CHECK_PROBE_DEFINE2(bpfdesc_check_receive, "struct bpf_d *", 351189503Srwatson "struct ifnet *"); 352189503Srwatson 353100979Srwatsonint 354172930Srwatsonmac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp) 355100979Srwatson{ 356100979Srwatson int error; 357100979Srwatson 358247629Smelifaro /* Assume reader lock is enough. */ 359168955Srwatson BPFD_LOCK_ASSERT(d); 360126406Srwatson 361193391Srwatson if (mac_policy_count == 0) 362193391Srwatson return (0); 363193391Srwatson 364168955Srwatson MAC_IFNET_LOCK(ifp); 365191731Srwatson MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp, 366189797Srwatson ifp->if_label); 367189503Srwatson MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp); 368168955Srwatson MAC_IFNET_UNLOCK(ifp); 369100979Srwatson 370100979Srwatson return (error); 371100979Srwatson} 372100979Srwatson 373189503SrwatsonMAC_CHECK_PROBE_DEFINE2(ifnet_check_transmit, "struct ifnet *", 374189503Srwatson "struct mbuf *"); 375189503Srwatson 376100979Srwatsonint 377172930Srwatsonmac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m) 378100979Srwatson{ 379113482Srwatson struct label *label; 380100979Srwatson int error; 381100979Srwatson 382168955Srwatson M_ASSERTPKTHDR(m); 383113487Srwatson 384193391Srwatson if (mac_policy_count == 0) 385193391Srwatson return (0); 386193391Srwatson 387168955Srwatson label = mac_mbuf_to_label(m); 388100979Srwatson 389168955Srwatson MAC_IFNET_LOCK(ifp); 390191731Srwatson MAC_POLICY_CHECK_NOSLEEP(ifnet_check_transmit, ifp, ifp->if_label, m, 391189797Srwatson label); 392189503Srwatson MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m); 393168955Srwatson MAC_IFNET_UNLOCK(ifp); 394100979Srwatson 395100979Srwatson return (error); 396100979Srwatson} 397100979Srwatson 398100979Srwatsonint 399172930Srwatsonmac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr, 400168955Srwatson struct ifnet *ifp) 401100979Srwatson{ 402105694Srwatson char *elements, *buffer; 403131025Srwatson struct label *intlabel; 404105694Srwatson struct mac mac; 405100979Srwatson int error; 406100979Srwatson 407182063Srwatson if (!(mac_labeled & MPC_OBJECT_IFNET)) 408182063Srwatson return (EINVAL); 409182063Srwatson 410105694Srwatson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 411100979Srwatson if (error) 412100979Srwatson return (error); 413100979Srwatson 414105694Srwatson error = mac_check_structmac_consistent(&mac); 415105694Srwatson if (error) 416105694Srwatson return (error); 417105694Srwatson 418111119Simp elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 419105694Srwatson error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 420105694Srwatson if (error) { 421105694Srwatson free(elements, M_MACTEMP); 422105694Srwatson return (error); 423105694Srwatson } 424105694Srwatson 425111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 426131025Srwatson intlabel = mac_ifnet_label_alloc(); 427168955Srwatson MAC_IFNET_LOCK(ifp); 428172930Srwatson mac_ifnet_copy_label(ifp->if_label, intlabel); 429168955Srwatson MAC_IFNET_UNLOCK(ifp); 430172930Srwatson error = mac_ifnet_externalize_label(intlabel, elements, buffer, 431165412Srwatson mac.m_buflen); 432131025Srwatson mac_ifnet_label_free(intlabel); 433105694Srwatson if (error == 0) 434105694Srwatson error = copyout(buffer, mac.m_string, strlen(buffer)+1); 435105694Srwatson 436105694Srwatson free(buffer, M_MACTEMP); 437105694Srwatson free(elements, M_MACTEMP); 438105694Srwatson 439105694Srwatson return (error); 440100979Srwatson} 441100979Srwatson 442100979Srwatsonint 443172930Srwatsonmac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp) 444100979Srwatson{ 445122524Srwatson struct label *intlabel; 446105694Srwatson struct mac mac; 447105694Srwatson char *buffer; 448100979Srwatson int error; 449100979Srwatson 450182063Srwatson if (!(mac_labeled & MPC_OBJECT_IFNET)) 451182063Srwatson return (EINVAL); 452182063Srwatson 453105694Srwatson error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac)); 454100979Srwatson if (error) 455100979Srwatson return (error); 456100979Srwatson 457105694Srwatson error = mac_check_structmac_consistent(&mac); 458100979Srwatson if (error) 459100979Srwatson return (error); 460100979Srwatson 461111119Simp buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 462105694Srwatson error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 463105694Srwatson if (error) { 464105694Srwatson free(buffer, M_MACTEMP); 465105694Srwatson return (error); 466105694Srwatson } 467105694Srwatson 468122524Srwatson intlabel = mac_ifnet_label_alloc(); 469172930Srwatson error = mac_ifnet_internalize_label(intlabel, buffer); 470105694Srwatson free(buffer, M_MACTEMP); 471105694Srwatson if (error) { 472122524Srwatson mac_ifnet_label_free(intlabel); 473105694Srwatson return (error); 474105694Srwatson } 475105694Srwatson 476100979Srwatson /* 477164033Srwatson * XXX: Note that this is a redundant privilege check, since policies 478165423Srwatson * impose this check themselves if required by the policy 479164033Srwatson * Eventually, this should go away. 480100979Srwatson */ 481164033Srwatson error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); 482105694Srwatson if (error) { 483122524Srwatson mac_ifnet_label_free(intlabel); 484105694Srwatson return (error); 485105694Srwatson } 486100979Srwatson 487168955Srwatson MAC_IFNET_LOCK(ifp); 488191731Srwatson MAC_POLICY_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp, 489191731Srwatson ifp->if_label, intlabel); 490105694Srwatson if (error) { 491168955Srwatson MAC_IFNET_UNLOCK(ifp); 492122524Srwatson mac_ifnet_label_free(intlabel); 493105694Srwatson return (error); 494105694Srwatson } 495100979Srwatson 496191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, ifp->if_label, 497189797Srwatson intlabel); 498168955Srwatson MAC_IFNET_UNLOCK(ifp); 499100979Srwatson 500122524Srwatson mac_ifnet_label_free(intlabel); 501105694Srwatson return (0); 502100979Srwatson} 503