aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2023-12-03 10:27:19 -0800
committerStephen Hemminger <stephen@networkplumber.org>2023-12-03 10:27:19 -0800
commit4913a5c2068cd51ae17307d4f201a1d94d216bd5 (patch)
tree62e9c1fa9a3b29a7a9784bbce41147aeb1683afd
parentac404c42314cac848a8c038e176f871828852518 (diff)
downloadiproute2-next-4913a5c2068cd51ae17307d4f201a1d94d216bd5.tar.gz
ip: require RTM_NEWLINK
The kernel support for creating network devices was added back in 2007 and iproute2 has been carrying backward compatability support since then. After 16 years, it is enough time to drop the code. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
-rw-r--r--ip/iplink.c492
1 files changed, 37 insertions, 455 deletions
diff --git a/ip/iplink.c b/ip/iplink.c
index 3ec4d9698..b02b94081 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -28,15 +28,12 @@
#include "ip_common.h"
#include "namespace.h"
-#define IPLINK_IOCTL_COMPAT 1
-
#ifndef GSO_MAX_SEGS
#define GSO_MAX_SEGS 65535
#endif
static void usage(void) __attribute__((noreturn));
-static int iplink_have_newlink(void);
void iplink_types_usage(void)
{
@@ -54,26 +51,22 @@ void iplink_types_usage(void)
void iplink_usage(void)
{
- if (iplink_have_newlink()) {
- fprintf(stderr,
- "Usage: ip link add [link DEV | parentdev NAME] [ name ] NAME\n"
- " [ txqueuelen PACKETS ]\n"
- " [ address LLADDR ]\n"
- " [ broadcast LLADDR ]\n"
- " [ mtu MTU ] [index IDX ]\n"
- " [ numtxqueues QUEUE_COUNT ]\n"
- " [ numrxqueues QUEUE_COUNT ]\n"
- " [ netns { PID | NETNSNAME | NETNSFILE } ]\n"
- " type TYPE [ ARGS ]\n"
- "\n"
- " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
- "\n"
- " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
- " [ { up | down } ]\n"
- " [ type TYPE ARGS ]\n");
- } else
- fprintf(stderr,
- "Usage: ip link set DEVICE [ { up | down } ]\n");
+ fprintf(stderr,
+ "Usage: ip link add [link DEV | parentdev NAME] [ name ] NAME\n"
+ " [ txqueuelen PACKETS ]\n"
+ " [ address LLADDR ]\n"
+ " [ broadcast LLADDR ]\n"
+ " [ mtu MTU ] [index IDX ]\n"
+ " [ numtxqueues QUEUE_COUNT ]\n"
+ " [ numrxqueues QUEUE_COUNT ]\n"
+ " [ netns { PID | NETNSNAME | NETNSFILE } ]\n"
+ " type TYPE [ ARGS ]\n"
+ "\n"
+ " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE [ ARGS ]\n"
+ "\n"
+ " ip link set { DEVICE | dev DEVICE | group DEVGROUP }\n"
+ " [ { up | down } ]\n"
+ " [ type TYPE ARGS ]\n");
fprintf(stderr,
" [ arp { on | off } ]\n"
@@ -126,13 +119,12 @@ void iplink_usage(void)
" ip link property add dev DEVICE [ altname NAME .. ]\n"
" ip link property del dev DEVICE [ altname NAME .. ]\n");
- if (iplink_have_newlink()) {
- fprintf(stderr,
- "\n"
- " ip link help [ TYPE ]\n"
- "\n");
- iplink_types_usage();
- }
+ fprintf(stderr,
+ "\n"
+ " ip link help [ TYPE ]\n"
+ "\n");
+ iplink_types_usage();
+
exit(-1);
}
@@ -206,51 +198,6 @@ static int get_addr_gen_mode(const char *mode)
return -1;
}
-#if IPLINK_IOCTL_COMPAT
-static int have_rtnl_newlink = -1;
-
-static int accept_msg(struct rtnl_ctrl_data *ctrl,
- struct nlmsghdr *n, void *arg)
-{
- struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(n);
-
- if (n->nlmsg_type == NLMSG_ERROR &&
- (err->error == -EOPNOTSUPP || err->error == -EINVAL))
- have_rtnl_newlink = 0;
- else
- have_rtnl_newlink = 1;
- return -1;
-}
-
-static int iplink_have_newlink(void)
-{
- struct {
- struct nlmsghdr n;
- struct ifinfomsg i;
- char buf[1024];
- } req = {
- .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
- .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
- .n.nlmsg_type = RTM_NEWLINK,
- .i.ifi_family = AF_UNSPEC,
- };
-
- if (have_rtnl_newlink < 0) {
- if (rtnl_send(&rth, &req.n, req.n.nlmsg_len) < 0) {
- perror("request send failed");
- exit(1);
- }
- rtnl_listen(&rth, accept_msg, NULL);
- }
- return have_rtnl_newlink;
-}
-#else /* IPLINK_IOCTL_COMPAT */
-static int iplink_have_newlink(void)
-{
- return 1;
-}
-#endif /* ! IPLINK_IOCTL_COMPAT */
-
static int nl_get_ll_addr_len(const char *ifname)
{
int len;
@@ -1181,363 +1128,6 @@ int iplink_get(char *name, __u32 filt_mask)
return 0;
}
-#if IPLINK_IOCTL_COMPAT
-static int get_ctl_fd(void)
-{
- int s_errno;
- int fd;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd >= 0)
- return fd;
- s_errno = errno;
- fd = socket(PF_PACKET, SOCK_DGRAM, 0);
- if (fd >= 0)
- return fd;
- fd = socket(PF_INET6, SOCK_DGRAM, 0);
- if (fd >= 0)
- return fd;
- errno = s_errno;
- perror("Cannot create control socket");
- return -1;
-}
-
-static int do_chflags(const char *dev, __u32 flags, __u32 mask)
-{
- struct ifreq ifr;
- int fd;
- int err;
-
- strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
- fd = get_ctl_fd();
- if (fd < 0)
- return -1;
- err = ioctl(fd, SIOCGIFFLAGS, &ifr);
- if (err) {
- perror("SIOCGIFFLAGS");
- close(fd);
- return -1;
- }
- if ((ifr.ifr_flags^flags)&mask) {
- ifr.ifr_flags &= ~mask;
- ifr.ifr_flags |= mask&flags;
- err = ioctl(fd, SIOCSIFFLAGS, &ifr);
- if (err)
- perror("SIOCSIFFLAGS");
- }
- close(fd);
- return err;
-}
-
-static int do_changename(const char *dev, const char *newdev)
-{
- struct ifreq ifr;
- int fd;
- int err;
-
- strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
- strlcpy(ifr.ifr_newname, newdev, IFNAMSIZ);
- fd = get_ctl_fd();
- if (fd < 0)
- return -1;
- err = ioctl(fd, SIOCSIFNAME, &ifr);
- if (err) {
- perror("SIOCSIFNAME");
- close(fd);
- return -1;
- }
- close(fd);
- return err;
-}
-
-static int set_qlen(const char *dev, int qlen)
-{
- struct ifreq ifr = { .ifr_qlen = qlen };
- int s;
-
- s = get_ctl_fd();
- if (s < 0)
- return -1;
-
- strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
- if (ioctl(s, SIOCSIFTXQLEN, &ifr) < 0) {
- perror("SIOCSIFXQLEN");
- close(s);
- return -1;
- }
- close(s);
-
- return 0;
-}
-
-static int set_mtu(const char *dev, int mtu)
-{
- struct ifreq ifr = { .ifr_mtu = mtu };
- int s;
-
- s = get_ctl_fd();
- if (s < 0)
- return -1;
-
- strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
- if (ioctl(s, SIOCSIFMTU, &ifr) < 0) {
- perror("SIOCSIFMTU");
- close(s);
- return -1;
- }
- close(s);
-
- return 0;
-}
-
-static int get_address(const char *dev, int *htype)
-{
- struct ifreq ifr = {};
- struct sockaddr_ll me = {
- .sll_family = AF_PACKET,
- .sll_protocol = htons(ETH_P_LOOP),
- };
- socklen_t alen;
- int s;
-
- s = socket(PF_PACKET, SOCK_DGRAM, 0);
- if (s < 0) {
- perror("socket(PF_PACKET)");
- return -1;
- }
-
- strlcpy(ifr.ifr_name, dev, IFNAMSIZ);
- if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
- perror("SIOCGIFINDEX");
- close(s);
- return -1;
- }
-
- me.sll_ifindex = ifr.ifr_ifindex;
- if (bind(s, (struct sockaddr *)&me, sizeof(me)) == -1) {
- perror("bind");
- close(s);
- return -1;
- }
-
- alen = sizeof(me);
- if (getsockname(s, (struct sockaddr *)&me, &alen) == -1) {
- perror("getsockname");
- close(s);
- return -1;
- }
- close(s);
- *htype = me.sll_hatype;
- return me.sll_halen;
-}
-
-static int parse_address(const char *dev, int hatype, int halen,
- char *lla, struct ifreq *ifr)
-{
- int alen;
-
- memset(ifr, 0, sizeof(*ifr));
- strlcpy(ifr->ifr_name, dev, IFNAMSIZ);
- ifr->ifr_hwaddr.sa_family = hatype;
- alen = ll_addr_a2n(ifr->ifr_hwaddr.sa_data, 14, lla);
- if (alen < 0)
- return -1;
- if (alen != halen) {
- fprintf(stderr,
- "Wrong address (%s) length: expected %d bytes\n",
- lla, halen);
- return -1;
- }
- return 0;
-}
-
-static int set_address(struct ifreq *ifr, int brd)
-{
- int s;
-
- s = get_ctl_fd();
- if (s < 0)
- return -1;
- if (ioctl(s, brd?SIOCSIFHWBROADCAST:SIOCSIFHWADDR, ifr) < 0) {
- perror(brd?"SIOCSIFHWBROADCAST":"SIOCSIFHWADDR");
- close(s);
- return -1;
- }
- close(s);
- return 0;
-}
-
-static int do_set(int argc, char **argv)
-{
- char *dev = NULL;
- __u32 mask = 0;
- __u32 flags = 0;
- int qlen = -1;
- int mtu = -1;
- char *newaddr = NULL;
- char *newbrd = NULL;
- struct ifreq ifr0, ifr1;
- char *newname = NULL;
- int htype, halen;
-
- while (argc > 0) {
- if (strcmp(*argv, "up") == 0) {
- mask |= IFF_UP;
- flags |= IFF_UP;
- } else if (strcmp(*argv, "down") == 0) {
- mask |= IFF_UP;
- 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();
- newaddr = *argv;
- } else if (matches(*argv, "broadcast") == 0 ||
- strcmp(*argv, "brd") == 0) {
- NEXT_ARG();
- newbrd = *argv;
- } else if (matches(*argv, "txqueuelen") == 0 ||
- strcmp(*argv, "qlen") == 0 ||
- matches(*argv, "txqlen") == 0) {
- NEXT_ARG();
- if (qlen != -1)
- duparg("txqueuelen", *argv);
- if (get_integer(&qlen, *argv, 0))
- invarg("Invalid \"txqueuelen\" value\n", *argv);
- } else if (strcmp(*argv, "mtu") == 0) {
- NEXT_ARG();
- if (mtu != -1)
- duparg("mtu", *argv);
- if (get_integer(&mtu, *argv, 0))
- invarg("Invalid \"mtu\" value\n", *argv);
- } else if (strcmp(*argv, "multicast") == 0) {
- NEXT_ARG();
- mask |= IFF_MULTICAST;
-
- if (strcmp(*argv, "on") == 0)
- flags |= IFF_MULTICAST;
- else if (strcmp(*argv, "off") == 0)
- flags &= ~IFF_MULTICAST;
- else
- return on_off("multicast", *argv);
- } else if (strcmp(*argv, "allmulticast") == 0) {
- NEXT_ARG();
- mask |= IFF_ALLMULTI;
-
- if (strcmp(*argv, "on") == 0)
- flags |= IFF_ALLMULTI;
- else if (strcmp(*argv, "off") == 0)
- flags &= ~IFF_ALLMULTI;
- else
- return on_off("allmulticast", *argv);
- } else if (strcmp(*argv, "promisc") == 0) {
- NEXT_ARG();
- mask |= IFF_PROMISC;
-
- if (strcmp(*argv, "on") == 0)
- flags |= IFF_PROMISC;
- else if (strcmp(*argv, "off") == 0)
- flags &= ~IFF_PROMISC;
- else
- return on_off("promisc", *argv);
- } else if (strcmp(*argv, "trailers") == 0) {
- NEXT_ARG();
- mask |= IFF_NOTRAILERS;
-
- if (strcmp(*argv, "off") == 0)
- flags |= IFF_NOTRAILERS;
- else if (strcmp(*argv, "on") == 0)
- flags &= ~IFF_NOTRAILERS;
- else
- return on_off("trailers", *argv);
- } else if (strcmp(*argv, "arp") == 0) {
- NEXT_ARG();
- mask |= IFF_NOARP;
-
- if (strcmp(*argv, "on") == 0)
- flags &= ~IFF_NOARP;
- else if (strcmp(*argv, "off") == 0)
- flags |= IFF_NOARP;
- else
- return on_off("arp", *argv);
- } else if (matches(*argv, "dynamic") == 0) {
- NEXT_ARG();
- mask |= IFF_DYNAMIC;
-
- if (strcmp(*argv, "on") == 0)
- flags |= IFF_DYNAMIC;
- else if (strcmp(*argv, "off") == 0)
- flags &= ~IFF_DYNAMIC;
- else
- return on_off("dynamic", *argv);
- } else {
- if (strcmp(*argv, "dev") == 0)
- NEXT_ARG();
- else if (matches(*argv, "help") == 0)
- usage();
-
- if (dev)
- duparg2("dev", *argv);
- if (check_ifname(*argv))
- invarg("\"dev\" not a valid ifname", *argv);
- dev = *argv;
- }
- argc--; argv++;
- }
-
- if (!dev) {
- fprintf(stderr,
- "Not enough of information: \"dev\" argument is required.\n");
- exit(-1);
- }
-
- if (newaddr || newbrd) {
- halen = get_address(dev, &htype);
- if (halen < 0)
- return -1;
- if (newaddr) {
- if (parse_address(dev, htype, halen,
- newaddr, &ifr0) < 0)
- return -1;
- }
- if (newbrd) {
- if (parse_address(dev, htype, halen,
- newbrd, &ifr1) < 0)
- return -1;
- }
- }
-
- if (newname && strcmp(dev, newname)) {
- if (do_changename(dev, newname) < 0)
- return -1;
- dev = newname;
- }
- if (qlen != -1) {
- if (set_qlen(dev, qlen) < 0)
- return -1;
- }
- if (mtu != -1) {
- if (set_mtu(dev, mtu) < 0)
- return -1;
- }
- if (newaddr || newbrd) {
- if (newbrd) {
- if (set_address(&ifr1, 1) < 0)
- return -1;
- }
- if (newaddr) {
- if (set_address(&ifr0, 0) < 0)
- return -1;
- }
- }
- if (mask)
- return do_chflags(dev, flags, mask);
- return 0;
-}
-#endif /* IPLINK_IOCTL_COMPAT */
void print_mpls_link_stats(FILE *fp, const struct mpls_link_stats *stats,
const char *indent)
@@ -1831,29 +1421,21 @@ int do_iplink(int argc, char **argv)
if (argc < 1)
return ipaddr_list_link(0, NULL);
- if (iplink_have_newlink()) {
- if (matches(*argv, "add") == 0)
- return iplink_modify(RTM_NEWLINK,
- NLM_F_CREATE|NLM_F_EXCL,
- argc-1, argv+1);
- if (matches(*argv, "set") == 0 ||
- matches(*argv, "change") == 0)
- return iplink_modify(RTM_NEWLINK, 0,
- argc-1, argv+1);
- if (matches(*argv, "replace") == 0)
- return iplink_modify(RTM_NEWLINK,
- NLM_F_CREATE|NLM_F_REPLACE,
- argc-1, argv+1);
- if (matches(*argv, "delete") == 0)
- return iplink_modify(RTM_DELLINK, 0,
- argc-1, argv+1);
- } else {
-#if IPLINK_IOCTL_COMPAT
- if (matches(*argv, "set") == 0)
- return do_set(argc-1, argv+1);
-#endif
- }
-
+ if (matches(*argv, "add") == 0)
+ return iplink_modify(RTM_NEWLINK,
+ NLM_F_CREATE|NLM_F_EXCL,
+ argc-1, argv+1);
+ if (matches(*argv, "set") == 0 ||
+ matches(*argv, "change") == 0)
+ return iplink_modify(RTM_NEWLINK, 0,
+ argc-1, argv+1);
+ if (matches(*argv, "replace") == 0)
+ return iplink_modify(RTM_NEWLINK,
+ NLM_F_CREATE|NLM_F_REPLACE,
+ argc-1, argv+1);
+ if (matches(*argv, "delete") == 0)
+ return iplink_modify(RTM_DELLINK, 0,
+ argc-1, argv+1);
if (matches(*argv, "show") == 0 ||
matches(*argv, "lst") == 0 ||
matches(*argv, "list") == 0)