void invarg(const char *, const char *) __attribute__((noreturn));
void duparg(const char *, const char *) __attribute__((noreturn));
void duparg2(const char *, const char *) __attribute__((noreturn));
+int check_ifname(const char *);
+int get_ifname(char *, const char *);
int matches(const char *arg, const char *pattern);
int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits);
usage();
if (p->name[0])
duparg2("name", *argv);
- strncpy(p->name, *argv, IFNAMSIZ - 1);
+ if (get_ifname(p->name, *argv))
+ invarg("\"name\" not a valid ifname", *argv);
if (cmd == SIOCCHGTUNNEL && count == 0) {
struct ip6_tnl_parm2 old_p = {};
if (p->peer_cookie_len)
addattr_l(&req.n, 1024, L2TP_ATTR_PEER_COOKIE,
p->peer_cookie, p->peer_cookie_len);
- if (p->ifname && p->ifname[0])
+ if (p->ifname)
addattrstrz(&req.n, 1024, L2TP_ATTR_IFNAME, p->ifname);
if (rtnl_talk(&genl_rth, &req.n, NULL, 0) < 0)
}
} else if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"name\" not a valid ifname", *argv);
p->ifname = *argv;
} else if (strcmp(*argv, "remote") == 0) {
NEXT_ARG();
req->i.ifi_flags &= ~IFF_UP;
} else if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"name\" not a valid ifname", *argv);
*name = *argv;
} else if (strcmp(*argv, "index") == 0) {
NEXT_ARG();
NEXT_ARG();
if (*dev)
duparg2("dev", *argv);
+ if (check_ifname(*argv))
+ invarg("\"dev\" not a valid ifname", *argv);
*dev = *argv;
dev_index = ll_name_to_index(*dev);
}
static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
{
- int len;
char *dev = NULL;
char *name = NULL;
char *link = NULL;
}
if (name) {
- len = strlen(name) + 1;
- if (len == 1)
- invarg("\"\" is not a valid device identifier\n",
- "name");
- if (len > IFNAMSIZ)
- invarg("\"name\" too long\n", name);
- addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len);
+ addattr_l(&req.n, sizeof(req),
+ IFLA_IFNAME, name, strlen(name) + 1);
}
if (type) {
int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
{
- int len;
struct iplink_req req = {
.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
.n.nlmsg_flags = NLM_F_REQUEST | flags,
} answer;
if (name) {
- len = strlen(name) + 1;
- if (len == 1)
- invarg("\"\" is not a valid device identifier\n",
- "name");
- if (len > IFNAMSIZ)
- invarg("\"name\" too long\n", name);
- addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, len);
+ addattr_l(&req.n, sizeof(req),
+ IFLA_IFNAME, name, strlen(name) + 1);
}
addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filt_mask);
flags &= ~IFF_UP;
} else if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"name\" not a valid ifname", *argv);
newname = *argv;
} else if (matches(*argv, "address") == 0) {
NEXT_ARG();
if (dev)
duparg2("dev", *argv);
+ if (check_ifname(*argv))
+ invarg("\"dev\" not a valid ifname", *argv);
dev = *argv;
}
argc--; argv++;
}
if (newname && strcmp(dev, newname)) {
- if (strlen(newname) == 0)
- invarg("\"\" is not a valid device identifier\n",
- "name");
if (do_changename(dev, newname) < 0)
return -1;
dev = newname;
NEXT_ARG();
if (ifr.ifr_name[0])
duparg("dev", *argv);
- strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
+ if (get_ifname(ifr.ifr_name, *argv))
+ invarg("\"dev\" not a valid ifname", *argv);
} else {
if (matches(*argv, "address") == 0) {
NEXT_ARG();
} else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "iif") == 0) {
NEXT_ARG();
- strncpy(filter.iif, *argv, IFNAMSIZ);
+ if (get_ifname(filter.iif, *argv))
+ invarg("\"iif\"/\"dev\" not a valid ifname", *argv);
filter.iifmask = 1;
} else if (strcmp(*argv, "oif") == 0) {
NEXT_ARG();
- strncpy(filter.oif, *argv, IFNAMSIZ);
+ if (get_ifname(filter.oif, *argv))
+ invarg("\"oif\" not a valid ifname", *argv);
filter.oifmask = 1;
} else if (strcmp(*argv, "l3mdev") == 0) {
filter.l3mdev = 1;
} else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "iif") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"iif\"/\"dev\" not a valid ifname", *argv);
addattr_l(&req.n, sizeof(req), FRA_IFNAME,
*argv, strlen(*argv)+1);
} else if (strcmp(*argv, "oif") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"oif\" not a valid ifname", *argv);
addattr_l(&req.n, sizeof(req), FRA_OIFNAME,
*argv, strlen(*argv)+1);
} else if (strcmp(*argv, "l3mdev") == 0) {
if (p->name[0])
duparg2("name", *argv);
- strncpy(p->name, *argv, IFNAMSIZ - 1);
+ if (get_ifname(p->name, *argv))
+ invarg("\"name\" not a valid ifname", *argv);
if (cmd == SIOCCHGTUNNEL && count == 0) {
struct ip_tunnel_parm old_p = {};
count++;
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"dev\" not a valid ifname", *argv);
medium = *argv;
} else {
fprintf(stderr,
cmd = SIOCDEL6RD;
} else if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"dev\" not a valid ifname", *argv);
medium = *argv;
} else {
fprintf(stderr,
ifr->ifr_flags |= IFF_MULTI_QUEUE;
} else if (matches(*argv, "dev") == 0) {
NEXT_ARG();
- strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1);
+ if (get_ifname(ifr->ifr_name, *argv))
+ invarg("\"dev\" not a valid ifname", *argv);
} else {
if (matches(*argv, "name") == 0) {
NEXT_ARG();
usage();
if (ifr->ifr_name[0])
duparg2("name", *argv);
- strncpy(ifr->ifr_name, *argv, IFNAMSIZ);
+ if (get_ifname(ifr->ifr_name, *argv))
+ invarg("\"name\" not a valid ifname", *argv);
}
count++;
argc--; argv++;
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
+#include <ctype.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <asm/types.h>
exit(-1);
}
+int check_ifname(const char *name)
+{
+ /* These checks mimic kernel checks in dev_valid_name */
+ if (*name == '\0')
+ return -1;
+ if (strlen(name) >= IFNAMSIZ)
+ return -1;
+
+ while (*name) {
+ if (*name == '/' || isspace(*name))
+ return -1;
+ ++name;
+ }
+ return 0;
+}
+
+/* buf is assumed to be IFNAMSIZ */
+int get_ifname(char *buf, const char *name)
+{
+ int ret;
+
+ ret = check_ifname(name);
+ if (ret == 0)
+ strncpy(buf, name, IFNAMSIZ);
+
+ return ret;
+}
+
int matches(const char *cmd, const char *pattern)
{
int len = strlen(cmd);
struct ifreq ifr = {};
for (i = 0; i < ifnum; i++) {
- strncpy(ifr.ifr_name, ifnames[i], IFNAMSIZ);
+ if (get_ifname(ifr.ifr_name, ifnames[i]))
+ invarg("not a valid ifname", ifnames[i]);
if (ioctl(udp_sock, SIOCGIFINDEX, &ifr)) {
perror("ioctl(SIOCGIFINDEX)");
exit(-1);
flags |= TCA_CLS_FLAGS_SKIP_SW;
} else if (matches(*argv, "indev") == 0) {
NEXT_ARG();
+ if (check_ifname(*argv))
+ invarg("\"indev\" not a valid ifname", *argv);
addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, *argv);
} else if (matches(*argv, "vlan_id") == 0) {
__u16 vid;