| 553 | } |
| 554 | |
| 555 | static void |
| 556 | tunclone(void *arg, struct ucred *cred, char *name, int namelen, |
| 557 | struct cdev **dev) |
| 558 | { |
| 559 | char devname[SPECNAMELEN + 1]; |
| 560 | struct tuntap_driver *drv; |
| 561 | int append_unit, i, u, tunflags; |
| 562 | bool mayclone; |
| 563 | |
| 564 | if (*dev != NULL) |
| 565 | return; |
| 566 | |
| 567 | tunflags = 0; |
| 568 | CURVNET_SET(CRED_TO_VNET(cred)); |
| 569 | if (tuntap_name2info(name, &u, &tunflags) != 0) |
| 570 | goto out; /* Not recognized */ |
| 571 | |
| 572 | if (u != -1 && u > IF_MAXUNIT) |
| 573 | goto out; /* Unit number too high */ |
| 574 | |
| 575 | mayclone = priv_check_cred(cred, PRIV_NET_IFCREATE) == 0; |
| 576 | if ((tunflags & TUN_L2) != 0) { |
| 577 | /* tap/vmnet allow user open with a sysctl */ |
| 578 | mayclone = (mayclone || tap_allow_uopen) && tapdclone; |
| 579 | } else { |
| 580 | mayclone = mayclone && tundclone; |
| 581 | } |
| 582 | |
| 583 | /* |
| 584 | * If tun cloning is enabled, only the superuser can create an |
| 585 | * interface. |
| 586 | */ |
| 587 | if (!mayclone) |
| 588 | goto out; |
| 589 | |
| 590 | if (u == -1) |
| 591 | append_unit = 1; |
| 592 | else |
| 593 | append_unit = 0; |
| 594 | |
| 595 | drv = tuntap_driver_from_flags(tunflags); |
| 596 | if (drv == NULL) |
| 597 | goto out; |
| 598 | |
| 599 | /* find any existing device, or allocate new unit number */ |
| 600 | i = clone_create(&drv->clones, &drv->cdevsw, &u, dev, 0); |
| 601 | if (i) { |
| 602 | if (append_unit) { |
| 603 | namelen = snprintf(devname, sizeof(devname), "%s%d", |
| 604 | name, u); |
| 605 | name = devname; |
| 606 | } |
| 607 | |
| 608 | i = tun_create_device(drv, u, cred, dev, name); |
| 609 | } |
| 610 | if (i == 0) |
| 611 | if_clone_create(name, namelen, NULL); |
| 612 | out: |
nothing calls this directly
no test coverage detected