Changeset View
Changeset View
Standalone View
Standalone View
head/sbin/ifconfig/ifvlan.c
Show First 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
#ifndef lint | #ifndef lint | ||||
static const char rcsid[] = | static const char rcsid[] = | ||||
"$FreeBSD$"; | "$FreeBSD$"; | ||||
#endif | #endif | ||||
#define NOTAG ((u_short) -1) | #define NOTAG ((u_short) -1) | ||||
static const char proto_8021Q[] = "802.1q"; | |||||
static const char proto_8021ad[] = "802.1ad"; | |||||
static struct vlanreq params = { | static struct vlanreq params = { | ||||
.vlr_tag = NOTAG, | .vlr_tag = NOTAG, | ||||
.vlr_proto = ETHERTYPE_VLAN, | |||||
}; | }; | ||||
static int | static int | ||||
getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) | getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq) | ||||
{ | { | ||||
bzero((char *)vreq, sizeof(*vreq)); | bzero((char *)vreq, sizeof(*vreq)); | ||||
ifr->ifr_data = (caddr_t)vreq; | ifr->ifr_data = (caddr_t)vreq; | ||||
return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); | return ioctl(s, SIOCGETVLAN, (caddr_t)ifr); | ||||
} | } | ||||
static void | static void | ||||
vlan_status(int s) | vlan_status(int s) | ||||
{ | { | ||||
struct vlanreq vreq; | struct vlanreq vreq; | ||||
if (getvlan(s, &ifr, &vreq) == -1) | if (getvlan(s, &ifr, &vreq) == -1) | ||||
return; | return; | ||||
printf("\tvlan: %d", vreq.vlr_tag); | printf("\tvlan: %d", vreq.vlr_tag); | ||||
printf(" vlanproto: "); | |||||
switch (vreq.vlr_proto) { | |||||
case ETHERTYPE_VLAN: | |||||
printf(proto_8021Q); | |||||
break; | |||||
case ETHERTYPE_QINQ: | |||||
printf(proto_8021ad); | |||||
break; | |||||
default: | |||||
printf("0x%04x", vreq.vlr_proto); | |||||
} | |||||
if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) | if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1) | ||||
printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); | printf(" vlanpcp: %u", ifr.ifr_vlan_pcp); | ||||
printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? | printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ? | ||||
"<none>" : vreq.vlr_parent); | "<none>" : vreq.vlr_parent); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
static int | |||||
vlan_match_ethervid(const char *name) | |||||
{ | |||||
return (strchr(name, '.') != NULL); | |||||
} | |||||
static void | static void | ||||
vlan_parse_ethervid(const char *name) | |||||
{ | |||||
char ifname[IFNAMSIZ]; | |||||
char *cp; | |||||
int vid; | |||||
strlcpy(ifname, name, IFNAMSIZ); | |||||
if ((cp = strrchr(ifname, '.')) == NULL) | |||||
return; | |||||
/* | |||||
* Don't mix vlan/vlandev parameters with dot notation. | |||||
*/ | |||||
if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') | |||||
errx(1, "ambiguous vlan specification"); | |||||
/* | |||||
* Derive params from interface name: "parent.vid". | |||||
*/ | |||||
*cp++ = '\0'; | |||||
if ((*cp < '1') || (*cp > '9')) | |||||
errx(1, "invalid vlan tag"); | |||||
vid = *cp++ - '0'; | |||||
while ((*cp >= '0') && (*cp <= '9')) | |||||
vid = (vid * 10) + (*cp++ - '0'); | |||||
if ((*cp != '\0') || (vid & ~0xFFF)) | |||||
errx(1, "invalid vlan tag"); | |||||
strlcpy(params.vlr_parent, ifname, IFNAMSIZ); | |||||
params.vlr_tag = (vid & 0xFFF); | |||||
} | |||||
static void | |||||
vlan_create(int s, struct ifreq *ifr) | vlan_create(int s, struct ifreq *ifr) | ||||
{ | { | ||||
vlan_parse_ethervid(ifr->ifr_name); | |||||
if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { | if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') { | ||||
/* | /* | ||||
* One or both parameters were specified, make sure both. | * One or both parameters were specified, make sure both. | ||||
*/ | */ | ||||
if (params.vlr_tag == NOTAG) | if (params.vlr_tag == NOTAG) | ||||
errx(1, "must specify a tag for vlan create"); | errx(1, "must specify a tag for vlan create"); | ||||
if (params.vlr_parent[0] == '\0') | if (params.vlr_parent[0] == '\0') | ||||
errx(1, "must specify a parent device for vlan create"); | errx(1, "must specify a parent device for vlan create"); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | DECL_CMD_FUNC(setvlandev, val, d) | ||||
strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); | strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent)); | ||||
if (getvlan(s, &ifr, &vreq) != -1) | if (getvlan(s, &ifr, &vreq) != -1) | ||||
vlan_set(s, &ifr); | vlan_set(s, &ifr); | ||||
} | } | ||||
static | static | ||||
DECL_CMD_FUNC(setvlanproto, val, d) | |||||
{ | |||||
struct vlanreq vreq; | |||||
if (strncasecmp(proto_8021Q, val, | |||||
strlen(proto_8021Q)) == 0) { | |||||
params.vlr_proto = ETHERTYPE_VLAN; | |||||
} else if (strncasecmp(proto_8021ad, val, | |||||
strlen(proto_8021ad)) == 0) { | |||||
params.vlr_proto = ETHERTYPE_QINQ; | |||||
} else | |||||
errx(1, "invalid value for vlanproto"); | |||||
if (getvlan(s, &ifr, &vreq) != -1) | |||||
vlan_set(s, &ifr); | |||||
} | |||||
static | |||||
DECL_CMD_FUNC(setvlanpcp, val, d) | DECL_CMD_FUNC(setvlanpcp, val, d) | ||||
{ | { | ||||
u_long ul; | u_long ul; | ||||
char *endp; | char *endp; | ||||
ul = strtoul(val, &endp, 0); | ul = strtoul(val, &endp, 0); | ||||
if (*endp != '\0') | if (*endp != '\0') | ||||
errx(1, "invalid value for vlanpcp"); | errx(1, "invalid value for vlanpcp"); | ||||
Show All 20 Lines | DECL_CMD_FUNC(unsetvlandev, val, d) | ||||
if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) | if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) | ||||
err(1, "SIOCSETVLAN"); | err(1, "SIOCSETVLAN"); | ||||
} | } | ||||
static struct cmd vlan_cmds[] = { | static struct cmd vlan_cmds[] = { | ||||
DEF_CLONE_CMD_ARG("vlan", setvlantag), | DEF_CLONE_CMD_ARG("vlan", setvlantag), | ||||
DEF_CLONE_CMD_ARG("vlandev", setvlandev), | DEF_CLONE_CMD_ARG("vlandev", setvlandev), | ||||
DEF_CLONE_CMD_ARG("vlanproto", setvlanproto), | |||||
DEF_CMD_ARG("vlanpcp", setvlanpcp), | DEF_CMD_ARG("vlanpcp", setvlanpcp), | ||||
/* NB: non-clone cmds */ | /* NB: non-clone cmds */ | ||||
DEF_CMD_ARG("vlan", setvlantag), | DEF_CMD_ARG("vlan", setvlantag), | ||||
DEF_CMD_ARG("vlandev", setvlandev), | DEF_CMD_ARG("vlandev", setvlandev), | ||||
DEF_CMD_ARG("vlanproto", setvlanproto), | |||||
/* XXX For compatibility. Should become DEF_CMD() some day. */ | /* XXX For compatibility. Should become DEF_CMD() some day. */ | ||||
DEF_CMD_OPTARG("-vlandev", unsetvlandev), | DEF_CMD_OPTARG("-vlandev", unsetvlandev), | ||||
DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), | DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap), | ||||
DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), | DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap), | ||||
DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), | DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap), | ||||
DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), | DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap), | ||||
DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), | DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap), | ||||
DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), | DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap), | ||||
Show All 12 Lines | |||||
vlan_ctor(void) | vlan_ctor(void) | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
for (i = 0; i < nitems(vlan_cmds); i++) | for (i = 0; i < nitems(vlan_cmds); i++) | ||||
cmd_register(&vlan_cmds[i]); | cmd_register(&vlan_cmds[i]); | ||||
af_register(&af_vlan); | af_register(&af_vlan); | ||||
callback_register(vlan_cb, NULL); | callback_register(vlan_cb, NULL); | ||||
clone_setdefcallback("vlan", vlan_create); | clone_setdefcallback_prefix("vlan", vlan_create); | ||||
clone_setdefcallback_filter(vlan_match_ethervid, vlan_create); | |||||
} | } |