Пример #1
0
static int multiq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			    struct nlmsghdr *n)
{
	struct tc_multiq_qopt opt;

	if (argc > 0) {
		if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
	return 0;
}
Пример #2
0
static int ingress_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{

	if (argc > 0) {
		while (argc > 0) {

			if (strcmp(*argv, "handle") == 0) {
				NEXT_ARG();
				argc--; argv++;
			} else {
				fprintf(stderr, "What is \"%s\"?\n", *argv);
				explain();
				return -1;
			}
		}
	}

	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	return 0;
}
Пример #3
0
int genl_resolve_family(struct rtnl_handle *grth, const char *family)
{
	GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
		     NLM_F_REQUEST);
	struct nlmsghdr *answer;
	int fnum;

	addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
		  family, strlen(family) + 1);

	if (rtnl_talk(grth, &req.n, &answer) < 0) {
		fprintf(stderr, "Error talking to the kernel\n");
		return -2;
	}

	fnum = genl_parse_getfamily(answer);
	free(answer);

	return fnum;
}
Пример #4
0
void TunManager::addRemoveTable(int ifIdx, RouterID rid, bool add) {
  // We just store default routes (one for IPv4 and one for IPv6) in each route
  // table.
  struct {
    struct nlmsghdr n;
    struct rtmsg r;
    char buf[256];
  } req;
  const folly::IPAddress addrs[] = {
    IPAddress{"0.0.0.0"},       // v4 default
    IPAddress{"::0"},           // v6 default
  };

  for (const auto& addr : addrs) {
    memset(&req, 0, sizeof(req));
    req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
    req.n.nlmsg_flags = NLM_F_REQUEST;
    if (add) {
      req.n.nlmsg_type = RTM_NEWROUTE;
      req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_REPLACE;
    } else {
      req.n.nlmsg_type = RTM_DELROUTE;
    }
    req.r.rtm_family = addr.family();
    req.r.rtm_table = getTableId(rid);
    req.r.rtm_scope = RT_SCOPE_NOWHERE;
    req.r.rtm_protocol = RTPROT_FBOSS;
    req.r.rtm_scope = RT_SCOPE_UNIVERSE;
    req.r.rtm_type = RTN_UNICAST;
    req.r.rtm_dst_len = 0;       // default route, /0
    addattr_l(&req.n, sizeof(req), RTA_DST, addr.bytes(), addr.byteCount());
    addattr32(&req.n, sizeof(req), RTA_OIF, ifIdx);
    auto ret = rtnl_talk(&rth_, &req.n, 0, 0, nullptr);
    sysCheckError(ret, "Failed to ", add ? "add" : "remove",
                  " default route ", addr, " @ index ", ifIdx,
                  " in table ", getTableId(rid), " for router ", rid);
    LOG(INFO) << (add ? "Added" : "Removed") << " default route " << addr
              << " @ index " << ifIdx << " in table " << getTableId(rid)
              << " for router " << rid;
  }
}
Пример #5
0
/* Utility functions */
static int
add_addr2req(struct nlmsghdr *n, int maxlen, int type, ip_address_t *ip_address)
{
	void *addr;
	int alen;

	if (!ip_address)
		return -1;

	if (IP_IS6(ip_address)) {
		addr = (void *) &ip_address->u.sin6_addr;
		alen = sizeof(ip_address->u.sin6_addr);
	}
	else
	{
	     addr = (void *) &ip_address->u.sin.sin_addr;
	     alen = sizeof(ip_address->u.sin.sin_addr);
	}

	return addattr_l(n, maxlen, type, addr, alen);
}
static int wrr_parse_opt(struct qdisc_util *qu, int argc, char **argv,
    struct nlmsghdr *n)
{
	struct tc_sfq_qopt opt;

	memset(&opt, 0, sizeof(opt));

	while (argc > 0) {
		/*
		if (strcmp(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_size(&opt.quantum, *argv)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
			ok++;
		} else if (strcmp(*argv, "perturb") == 0) {
			NEXT_ARG();
			if (get_integer(&opt.perturb_period, *argv, 0)) {
				fprintf(stderr, "Illegal \"perturb\"\n");
				return -1;
			}
			ok++;
		} else*/ if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
	return 0;
}
Пример #7
0
static int qfq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
			       struct nlmsghdr *n)
{
	struct rtattr *tail;
	__u32 tmp;

	tail = NLMSG_TAIL(n);
	addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);

	while (argc > 0) {
		if (matches(*argv, "weight") == 0) {
			NEXT_ARG();
			if (get_u32(&tmp, *argv, 10)) {
				explain1("weight"); return -1;
			}
			addattr32(n, 4096, TCA_QFQ_WEIGHT, tmp);
		} else if (matches(*argv, "maxpkt") == 0) {
			NEXT_ARG();
			if (get_u32(&tmp, *argv, 10)) {
				explain1("maxpkt"); return -1;
			}
			addattr32(n, 4096, TCA_QFQ_LMAX, tmp);
		} else if (strcmp(*argv, "help") == 0) {
			explain_class();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain_class();
			return -1;
		}
		argc--; argv++;
	}

	tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;

	return 0;
}
Пример #8
0
bool set_ip4(int iface_index, uint32_t address, uint8_t network)
{
	bool is_success = false;
	int ret;
	struct {
		struct nlmsghdr nh;
		struct ifaddrmsg ip;
		char buf[256];
	} req;
	struct rtnl_handle rth = { .fd = -1 };
	uint32_t *ip_data;

	ret = rtnl_open(&rth, 0);
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to open RTNL socket (code %d)", ret);
		goto error;
	}

	ip_data = calloc(8, sizeof(uint32_t));
	if(ip_data == NULL)
	{
		trace(LOG_ERR, "failed to allocate memory for setting IPv4 address");
		goto close_rtnl;
	}
	ip_data[0] = address;

	/* initialize netlink request */
	memset(&req, 0, sizeof(req));
	req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
	req.nh.nlmsg_type = RTM_NEWADDR;

	/* ifaddrmsg info */
	req.ip.ifa_family = AF_INET;         /* IPv4 */
	req.ip.ifa_prefixlen = network;
	req.ip.ifa_index = iface_index;

	addattr_l(&req.nh, sizeof(req), IFA_LOCAL,   ip_data, 4);
	addattr_l(&req.nh, sizeof(req), IFA_ADDRESS, ip_data, 4);

	/* GOGOGO */
#if RTNL_TALK_PARAMS == 5
	ret = rtnl_talk(&rth, &req.nh, 0, 0, NULL);
#elif RTNL_TALK_PARAMS == 7
	ret = rtnl_talk(&rth, &req.nh, 0, 0, NULL, NULL, NULL);
#else
#  error "unsupported version of rtnl_talk()"
#endif
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to set IPv4 address %u.%u.%u.%u/%u (code %d)",
		      (ntohl(address) >> 24) & 0xff, (ntohl(address) >> 16) & 0xff,
		      (ntohl(address) >>  8) & 0xff, (ntohl(address) >>  0) & 0xff,
		      network, ret);
		goto free_ip_data;
	}

	is_success = true;

free_ip_data:
	free(ip_data);
close_rtnl:
	rtnl_close(&rth);
error:
	return is_success;
}
Пример #9
0
static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
{
    int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6;
    struct tc_rsvp_pinfo pinfo;
    struct tc_police tp;
    struct tcmsg *t = NLMSG_DATA(n);
    int pinfo_ok = 0;
    struct rtattr *tail;

    memset(&pinfo, 0, sizeof(pinfo));
    memset(&tp, 0, sizeof(tp));

    if (handle) {
        if (get_u32(&t->tcm_handle, handle, 0)) {
            my_printf("Illegal \"handle\"\n");
            return -1;
        }
    }

    if (argc == 0)
        return 0;

    tail = NLMSG_TAIL(n);
    addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);

    while (argc > 0) {
        if (matches(*argv, "session") == 0) {
            inet_prefix addr;
            NEXT_ARG();
            if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 1, family)) {
                my_printf("Illegal \"session\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_DST, &addr.data, addr.bytelen);
            if (pinfo.dpi.mask || pinfo.protocol)
                pinfo_ok++;
            continue;
        } else if (matches(*argv, "sender") == 0 ||
                   matches(*argv, "flowspec") == 0) {
            inet_prefix addr;
            NEXT_ARG();
            if (get_addr_and_pi(&argc, &argv, &addr, &pinfo, 0, family)) {
                my_printf("Illegal \"sender\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_SRC, &addr.data, addr.bytelen);
            if (pinfo.spi.mask || pinfo.protocol)
                pinfo_ok++;
            continue;
        } else if (matches("ipproto", *argv) == 0) {
            int num;
            NEXT_ARG();
            num = inet_proto_a2n(*argv);
            if (num < 0) {
                my_printf("Illegal \"ipproto\"\n");
                return -1;
            }
            pinfo.protocol = num;
            pinfo_ok++;
        } else if (matches(*argv, "classid") == 0 ||
                   strcmp(*argv, "flowid") == 0) {
            unsigned handle;
            NEXT_ARG();
            if (get_tc_classid(&handle, *argv)) {
                my_printf("Illegal \"classid\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_CLASSID, &handle, 4);
        } else if (strcmp(*argv, "tunnelid") == 0) {
            unsigned tid;
            NEXT_ARG();
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"tunnelid\"\n");
                return -1;
            }
            pinfo.tunnelid = tid;
            pinfo_ok++;
        } else if (strcmp(*argv, "tunnel") == 0) {
            unsigned tid;
            NEXT_ARG();
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"tunnel\"\n");
                return -1;
            }
            addattr_l(n, 4096, TCA_RSVP_CLASSID, &tid, 4);
            NEXT_ARG();
            if (strcmp(*argv, "skip") == 0) {
                NEXT_ARG();
            }
            if (get_unsigned(&tid, *argv, 0)) {
                my_printf("Illegal \"skip\"\n");
                return -1;
            }
            pinfo.tunnelhdr = tid;
            pinfo_ok++;
        } else if (matches(*argv, "police") == 0) {
            NEXT_ARG();
            if (parse_police(&argc, &argv, TCA_RSVP_POLICE, n)) {
                my_printf("Illegal \"police\"\n");
                return -1;
            }
            continue;
        } else if (strcmp(*argv, "help") == 0) {
            explain();
            return -1;
        } else {
            my_printf("What is \"%s\"?\n", *argv);
            explain();
            return -1;
        }
        argc--;
        argv++;
    }

    if (pinfo_ok)
        addattr_l(n, 4096, TCA_RSVP_PINFO, &pinfo, sizeof(pinfo));
    tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
    return 0;
}
Пример #10
0
static int fdb_modify(int cmd, int flags, int argc, char **argv)
{
	struct {
		struct nlmsghdr 	n;
		struct ndmsg 		ndm;
		char   			buf[256];
	} req;
	char *addr = NULL;
	char *d = NULL;
	char abuf[ETH_ALEN];
	int dst_ok = 0;
	inet_prefix dst;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = cmd;
	req.ndm.ndm_family = PF_BRIDGE;
	req.ndm.ndm_state = NUD_NOARP;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			d = *argv;
		} else if (strcmp(*argv, "dst") == 0) {
			NEXT_ARG();
			if (dst_ok)
				duparg2("dst", *argv);
			get_addr(&dst, *argv, preferred_family);
			dst_ok = 1;
		} else if (strcmp(*argv, "self") == 0) {
			req.ndm.ndm_flags |= NTF_SELF;
		} else if (matches(*argv, "master") == 0) {
			req.ndm.ndm_flags |= NTF_MASTER;
		} else if (matches(*argv, "local") == 0||
			   matches(*argv, "permanent") == 0) {
			req.ndm.ndm_state |= NUD_PERMANENT;
		} else if (matches(*argv, "temp") == 0) {
			req.ndm.ndm_state |= NUD_REACHABLE;
		} else {
			if (strcmp(*argv, "to") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			if (addr)
				duparg2("to", *argv);
			addr = *argv;
		}
		argc--; argv++;
	}

	if (d == NULL || addr == NULL) {
		fprintf(stderr, "Device and address are required arguments.\n");
		exit(-1);
	}

	/* Assume self */
	if (!(req.ndm.ndm_flags&(NTF_SELF|NTF_MASTER)))
		req.ndm.ndm_flags |= NTF_SELF;

	/* Assume permanent */
	if (!(req.ndm.ndm_state&(NUD_PERMANENT|NUD_REACHABLE)))
		req.ndm.ndm_state |= NUD_PERMANENT;

	if (sscanf(addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
		   abuf, abuf+1, abuf+2,
		   abuf+3, abuf+4, abuf+5) != 6) {
		fprintf(stderr, "Invalid mac address %s\n", addr);
		exit(-1);
	}

	addattr_l(&req.n, sizeof(req), NDA_LLADDR, abuf, ETH_ALEN);
	if (dst_ok)
		addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen);

	req.ndm.ndm_ifindex = ll_name_to_index(d);
	if (req.ndm.ndm_ifindex == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", d);
		return -1;
	}

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
		exit(2);

	return 0;
}
Пример #11
0
/* Return value becomes exitcode. It's okay to not return at all */
static int ipaddr_modify(int cmd, int argc, char **argv)
{
	static const char option[] ALIGN1 =
		"peer\0""remote\0""broadcast\0""brd\0"
		"anycast\0""scope\0""dev\0""label\0""local\0";
	struct rtnl_handle rth;
	struct {
		struct nlmsghdr  n;
		struct ifaddrmsg ifa;
		char             buf[256];
	} req;
	char *d = NULL;
	char *l = NULL;
	inet_prefix lcl;
	inet_prefix peer;
	int local_len = 0;
	int peer_len = 0;
	int brd_len = 0;
	int any_len = 0;
	bool scoped = 0;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_type = cmd;
	req.ifa.ifa_family = preferred_family;

	while (argc > 0) {
		const int option_num = index_in_strings(option, *argv);
		switch (option_num) {
			case 0: /* peer */
			case 1: /* remote */
				NEXT_ARG();

				if (peer_len) {
					duparg("peer", *argv);
				}
				get_prefix(&peer, *argv, req.ifa.ifa_family);
				peer_len = peer.bytelen;
				if (req.ifa.ifa_family == AF_UNSPEC) {
					req.ifa.ifa_family = peer.family;
				}
				addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &peer.data, peer.bytelen);
				req.ifa.ifa_prefixlen = peer.bitlen;
				break;
			case 2: /* broadcast */
			case 3: /* brd */
			{
				inet_prefix addr;
				NEXT_ARG();
				if (brd_len) {
					duparg("broadcast", *argv);
				}
				if (LONE_CHAR(*argv, '+')) {
					brd_len = -1;
				}
				else if (LONE_DASH(*argv)) {
					brd_len = -2;
				} else {
					get_addr(&addr, *argv, req.ifa.ifa_family);
					if (req.ifa.ifa_family == AF_UNSPEC)
						req.ifa.ifa_family = addr.family;
					addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen);
					brd_len = addr.bytelen;
				}
				break;
			}
			case 4: /* anycast */
			{
				inet_prefix addr;
				NEXT_ARG();
				if (any_len) {
					duparg("anycast", *argv);
				}
				get_addr(&addr, *argv, req.ifa.ifa_family);
				if (req.ifa.ifa_family == AF_UNSPEC) {
					req.ifa.ifa_family = addr.family;
				}
				addattr_l(&req.n, sizeof(req), IFA_ANYCAST, &addr.data, addr.bytelen);
				any_len = addr.bytelen;
				break;
			}
			case 5: /* scope */
			{
				uint32_t scope = 0;
				NEXT_ARG();
				if (rtnl_rtscope_a2n(&scope, *argv)) {
					invarg(*argv, "scope");
				}
				req.ifa.ifa_scope = scope;
				scoped = 1;
				break;
			}
			case 6: /* dev */
				NEXT_ARG();
				d = *argv;
				break;
			case 7: /* label */
				NEXT_ARG();
				l = *argv;
				addattr_l(&req.n, sizeof(req), IFA_LABEL, l, strlen(l)+1);
				break;
			case 8:	/* local */
				NEXT_ARG();
			default:
				if (local_len) {
					duparg2("local", *argv);
				}
				get_prefix(&lcl, *argv, req.ifa.ifa_family);
				if (req.ifa.ifa_family == AF_UNSPEC) {
					req.ifa.ifa_family = lcl.family;
				}
				addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen);
				local_len = lcl.bytelen;
		}
		argc--;
		argv++;
	}

	if (d == NULL) {
		bb_error_msg(bb_msg_requires_arg,"\"dev\"");
		return -1;
	}
	if (l && strncmp(d, l, strlen(d)) != 0) {
		bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l);
	}

	if (peer_len == 0 && local_len && cmd != RTM_DELADDR) {
		peer = lcl;
		addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &lcl.data, lcl.bytelen);
	}
	if (req.ifa.ifa_prefixlen == 0)
		req.ifa.ifa_prefixlen = lcl.bitlen;

	if (brd_len < 0 && cmd != RTM_DELADDR) {
		inet_prefix brd;
		int i;
		if (req.ifa.ifa_family != AF_INET) {
			bb_error_msg_and_die("broadcast can be set only for IPv4 addresses");
		}
		brd = peer;
		if (brd.bitlen <= 30) {
			for (i=31; i>=brd.bitlen; i--) {
				if (brd_len == -1)
					brd.data[0] |= htonl(1<<(31-i));
				else
					brd.data[0] &= ~htonl(1<<(31-i));
			}
			addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &brd.data, brd.bytelen);
			brd_len = brd.bytelen;
		}
	}
	if (!scoped && cmd != RTM_DELADDR)
		req.ifa.ifa_scope = default_scope(&lcl);

	xrtnl_open(&rth);

	ll_init_map(&rth);

	req.ifa.ifa_index = xll_name_to_index(d);

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		return 2;

	return 0;
}
Пример #12
0
int
parse_gact(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
    int argc = *argc_p;
    char **argv = *argv_p;
    int ok = 0;
    int action = TC_POLICE_RECLASSIFY;
    struct tc_gact p;
#ifdef CONFIG_GACT_PROB
    int rd = 0;
    struct tc_gact_p pp;
#endif
    struct rtattr *tail;

    memset(&p, 0, sizeof (p));
    p.action = TC_POLICE_RECLASSIFY;

    if (argc < 0)
        return -1;


    if (matches(*argv, "gact") == 0) {
        ok++;
    } else {
        action = get_act(&argv);
        if (action != -10) {
            p.action = action;
            ok++;
        } else {
            explain();
            return action;
        }
    }

    if (ok) {
        argc--;
        argv++;
    }

#ifdef CONFIG_GACT_PROB
    if (ok && argc > 0) {
        if (matches(*argv, "random") == 0) {
            rd = 1;
            NEXT_ARG();
            if (matches(*argv, "netrand") == 0) {
                NEXT_ARG();
                pp.ptype = PGACT_NETRAND;
            } else if  (matches(*argv, "determ") == 0) {
                NEXT_ARG();
                pp.ptype = PGACT_DETERM;
            } else {
                fprintf(stderr, "Illegal \"random type\"\n");
                return -1;
            }

            action = get_act(&argv);
            if (action != -10) { /* FIXME */
                pp.paction = action;
            } else {
                explain();
                return -1;
            }
            argc--;
            argv++;
            if (get_u16(&pp.pval, *argv, 10)) {
                fprintf(stderr, "Illegal probability val 0x%x\n",pp.pval);
                return -1;
            }
            if (pp.pval > 10000) {
                fprintf(stderr, "Illegal probability val  0x%x\n",pp.pval);
                return -1;
            }
            argc--;
            argv++;
        }
    }
#endif

    if (argc > 0) {
        if (matches(*argv, "index") == 0) {
            NEXT_ARG();
            if (get_u32(&p.index, *argv, 10)) {
                fprintf(stderr, "Illegal \"index\"\n");
                return -1;
            }
            argc--;
            argv++;
            ok++;
        }
    }

    if (!ok)
        return -1;

    tail = NLMSG_TAIL(n);
    addattr_l(n, MAX_MSG, tca_id, NULL, 0);
    addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof (p));
#ifdef CONFIG_GACT_PROB
    if (rd) {
        addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof (pp));
    }
#endif
    tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;

    *argc_p = argc;
    *argv_p = argv;
    return 0;
}
Пример #13
0
int
parse_pedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	struct {
		struct tc_pedit_sel sel;
		struct tc_pedit_key keys[MAX_OFFS];
	} sel;

	int argc = *argc_p;
	char **argv = *argv_p;
	int ok = 0, iok = 0;
	struct rtattr *tail;

	memset(&sel, 0, sizeof(sel));

	while (argc > 0) {
		if (pedit_debug > 1)
			fprintf(stderr, "while pedit (%d:%s)\n",argc, *argv);
		if (matches(*argv, "pedit") == 0) {
			NEXT_ARG();
			ok++;
			continue;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else if (matches(*argv, "munge") == 0) {
			if (!ok) {
				fprintf(stderr, "Illegal pedit construct (%s) \n", *argv);
				explain();
				return -1;
			}
			NEXT_ARG();
			if (parse_munge(&argc, &argv,&sel.sel)) {
				fprintf(stderr, "Illegal pedit construct (%s) \n", *argv);
				explain();
				return -1;
			}
			ok++;
		} else {
			break;
		}

	}

	if (!ok) {
		explain();
		return -1;
	}

	if (argc) {
		if (matches(*argv, "reclassify") == 0) {
			sel.sel.action = TC_ACT_RECLASSIFY;
			NEXT_ARG();
		} else if (matches(*argv, "pipe") == 0) {
			sel.sel.action = TC_ACT_PIPE;
			NEXT_ARG();
		} else if (matches(*argv, "drop") == 0 ||
			matches(*argv, "shot") == 0) {
			sel.sel.action = TC_ACT_SHOT;
			NEXT_ARG();
		} else if (matches(*argv, "continue") == 0) {
			sel.sel.action = TC_ACT_UNSPEC;
			NEXT_ARG();
		} else if (matches(*argv, "pass") == 0) {
			sel.sel.action = TC_ACT_OK;
			NEXT_ARG();
		}
	}

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.sel.index, *argv, 10)) {
				fprintf(stderr, "Pedit: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
			iok++;
		}
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
	addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS,&sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_pedit_key));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}
Пример #14
0
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
                              struct nlmsghdr *n)
{
    struct {
        struct nlmsghdr n;
        struct ifinfomsg i;
        char buf[2048];
    } req;
    struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
    struct rtattr *tb[IFLA_MAX + 1];
    struct rtattr *linkinfo[IFLA_INFO_MAX+1];
    struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
    int len;
    __u32 link = 0;
    __u32 laddr = 0;
    __u32 raddr = 0;
    __u8 ttl = 0;
    __u8 tos = 0;
    __u8 pmtudisc = 1;
    __u16 iflags = 0;
    __u8 proto = 0;
    struct in6_addr ip6rdprefix;
    __u16 ip6rdprefixlen = 0;
    __u32 ip6rdrelayprefix = 0;
    __u16 ip6rdrelayprefixlen = 0;

    memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));

    if (!(n->nlmsg_flags & NLM_F_CREATE)) {
        memset(&req, 0, sizeof(req));

        req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
        req.n.nlmsg_flags = NLM_F_REQUEST;
        req.n.nlmsg_type = RTM_GETLINK;
        req.i.ifi_family = preferred_family;
        req.i.ifi_index = ifi->ifi_index;

        if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
get_failed:
            fprintf(stderr,
                    "Failed to get existing tunnel info.\n");
            return -1;
        }

        len = req.n.nlmsg_len;
        len -= NLMSG_LENGTH(sizeof(*ifi));
        if (len < 0)
            goto get_failed;

        parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);

        if (!tb[IFLA_LINKINFO])
            goto get_failed;

        parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);

        if (!linkinfo[IFLA_INFO_DATA])
            goto get_failed;

        parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
                            linkinfo[IFLA_INFO_DATA]);

        if (iptuninfo[IFLA_IPTUN_LOCAL])
            laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);

        if (iptuninfo[IFLA_IPTUN_REMOTE])
            raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);

        if (iptuninfo[IFLA_IPTUN_TTL])
            ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);

        if (iptuninfo[IFLA_IPTUN_TOS])
            tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);

        if (iptuninfo[IFLA_IPTUN_PMTUDISC])
            pmtudisc =
                rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);

        if (iptuninfo[IFLA_IPTUN_FLAGS])
            iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);

        if (iptuninfo[IFLA_IPTUN_LINK])
            link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);

        if (iptuninfo[IFLA_IPTUN_PROTO])
            proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]);

        if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
            memcpy(&ip6rdprefix,
                   RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
                   sizeof(laddr));

        if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
            ip6rdprefixlen =
                rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);

        if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
            ip6rdrelayprefix =
                rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);

        if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
            ip6rdrelayprefixlen =
                rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
    }

    while (argc > 0) {
        if (strcmp(*argv, "remote") == 0) {
            NEXT_ARG();
            if (strcmp(*argv, "any"))
                raddr = get_addr32(*argv);
            else
                raddr = 0;
        } else if (strcmp(*argv, "local") == 0) {
            NEXT_ARG();
            if (strcmp(*argv, "any"))
                laddr = get_addr32(*argv);
            else
                laddr = 0;
        } else if (matches(*argv, "dev") == 0) {
            NEXT_ARG();
            link = if_nametoindex(*argv);
            if (link == 0)
                invarg("\"dev\" is invalid", *argv);
        } else if (strcmp(*argv, "ttl") == 0 ||
                   strcmp(*argv, "hoplimit") == 0) {
            NEXT_ARG();
            if (strcmp(*argv, "inherit") != 0) {
                if (get_u8(&ttl, *argv, 0))
                    invarg("invalid TTL\n", *argv);
            } else
                ttl = 0;
        } else if (strcmp(*argv, "tos") == 0 ||
                   strcmp(*argv, "tclass") == 0 ||
                   matches(*argv, "dsfield") == 0) {
            __u32 uval;
            NEXT_ARG();
            if (strcmp(*argv, "inherit") != 0) {
                if (rtnl_dsfield_a2n(&uval, *argv))
                    invarg("bad TOS value", *argv);
                tos = uval;
            } else
                tos = 1;
        } else if (strcmp(*argv, "nopmtudisc") == 0) {
            pmtudisc = 0;
        } else if (strcmp(*argv, "pmtudisc") == 0) {
            pmtudisc = 1;
        } else if (strcmp(lu->id, "sit") == 0 &&
                   strcmp(*argv, "isatap") == 0) {
            iflags |= SIT_ISATAP;
        } else if (strcmp(lu->id, "sit") == 0 &&
                   strcmp(*argv, "mode") == 0) {
            NEXT_ARG();
            if (strcmp(*argv, "ipv6/ipv4") == 0 ||
                    strcmp(*argv, "ip6ip") == 0)
                proto = IPPROTO_IPV6;
            else if (strcmp(*argv, "ipv4/ipv4") == 0 ||
                     strcmp(*argv, "ipip") == 0 ||
                     strcmp(*argv, "ip4ip4") == 0)
                proto = IPPROTO_IPIP;
            else if (strcmp(*argv, "any/ipv4") == 0 ||
                     strcmp(*argv, "any") == 0)
                proto = 0;
            else
                invarg("Cannot guess tunnel mode.", *argv);
        } else if (strcmp(*argv, "6rd-prefix") == 0) {
            inet_prefix prefix;
            NEXT_ARG();
            if (get_prefix(&prefix, *argv, AF_INET6))
                invarg("invalid 6rd_prefix\n", *argv);
            memcpy(&ip6rdprefix, prefix.data, 16);
            ip6rdprefixlen = prefix.bitlen;
        } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
            inet_prefix prefix;
            NEXT_ARG();
            if (get_prefix(&prefix, *argv, AF_INET))
                invarg("invalid 6rd-relay_prefix\n", *argv);
            memcpy(&ip6rdrelayprefix, prefix.data, 4);
            ip6rdrelayprefixlen = prefix.bitlen;
        } else if (strcmp(*argv, "6rd-reset") == 0) {
            inet_prefix prefix;
            get_prefix(&prefix, "2002::", AF_INET6);
            memcpy(&ip6rdprefix, prefix.data, 16);
            ip6rdprefixlen = 16;
            ip6rdrelayprefix = 0;
            ip6rdrelayprefixlen = 0;
        } else
            usage(strcmp(lu->id, "sit") == 0);
        argc--, argv++;
    }

    if (ttl && pmtudisc == 0) {
        fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
        exit(-1);
    }

    addattr32(n, 1024, IFLA_IPTUN_LINK, link);
    addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
    addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
    addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
    addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
    addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
    if (strcmp(lu->id, "sit") == 0) {
        addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
        addattr8(n, 1024, IFLA_IPTUN_PROTO, proto);
        if (ip6rdprefixlen) {
            addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
                      &ip6rdprefix, sizeof(ip6rdprefix));
            addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
                      ip6rdprefixlen);
            addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
                      ip6rdrelayprefix);
            addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
                      ip6rdrelayprefixlen);
        }
    }

    return 0;
}
Пример #15
0
static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
			  struct nlmsghdr *n)
{
	__u8 mode, use_carrier, primary_reselect, fail_over_mac;
	__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
	__u8 lacp_rate, ad_select, tlb_dynamic_lb;
	__u16 ad_user_port_key, ad_actor_sys_prio;
	__u32 miimon, updelay, downdelay, arp_interval, arp_validate;
	__u32 arp_all_targets, resend_igmp, min_links, lp_interval;
	__u32 packets_per_slave;
	unsigned ifindex;

	while (argc > 0) {
		if (matches(*argv, "mode") == 0) {
			NEXT_ARG();
			if (get_index(mode_tbl, *argv) < 0)
				invarg("invalid mode", *argv);
			mode = get_index(mode_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_MODE, mode);
		} else if (matches(*argv, "active_slave") == 0) {
			NEXT_ARG();
			ifindex = if_nametoindex(*argv);
			if (!ifindex)
				return -1;
			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
		} else if (matches(*argv, "clear_active_slave") == 0) {
			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
		} else if (matches(*argv, "miimon") == 0) {
			NEXT_ARG();
			if (get_u32(&miimon, *argv, 0))
				invarg("invalid miimon", *argv);
			addattr32(n, 1024, IFLA_BOND_MIIMON, miimon);
		} else if (matches(*argv, "updelay") == 0) {
			NEXT_ARG();
			if (get_u32(&updelay, *argv, 0))
				invarg("invalid updelay", *argv);
			addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay);
		} else if (matches(*argv, "downdelay") == 0) {
			NEXT_ARG();
			if (get_u32(&downdelay, *argv, 0))
				invarg("invalid downdelay", *argv);
			addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay);
		} else if (matches(*argv, "use_carrier") == 0) {
			NEXT_ARG();
			if (get_u8(&use_carrier, *argv, 0))
				invarg("invalid use_carrier", *argv);
			addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier);
		} else if (matches(*argv, "arp_interval") == 0) {
			NEXT_ARG();
			if (get_u32(&arp_interval, *argv, 0))
				invarg("invalid arp_interval", *argv);
			addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval);
		} else if (matches(*argv, "arp_ip_target") == 0) {
			struct rtattr * nest = addattr_nest(n, 1024,
				IFLA_BOND_ARP_IP_TARGET);
			if (NEXT_ARG_OK()) {
				NEXT_ARG();
				char *targets = strdupa(*argv);
				char *target = strtok(targets, ",");
				int i;

				for(i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) {
					__u32 addr = get_addr32(target);
					addattr32(n, 1024, i, addr);
					target = strtok(NULL, ",");
				}
				addattr_nest_end(n, nest);
			}
			addattr_nest_end(n, nest);
		} else if (matches(*argv, "arp_validate") == 0) {
			NEXT_ARG();
			if (get_index(arp_validate_tbl, *argv) < 0)
				invarg("invalid arp_validate", *argv);
			arp_validate = get_index(arp_validate_tbl, *argv);
			addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate);
		} else if (matches(*argv, "arp_all_targets") == 0) {
			NEXT_ARG();
			if (get_index(arp_all_targets_tbl, *argv) < 0)
				invarg("invalid arp_all_targets", *argv);
			arp_all_targets = get_index(arp_all_targets_tbl, *argv);
			addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets);
		} else if (matches(*argv, "primary") == 0) {
			NEXT_ARG();
			ifindex = if_nametoindex(*argv);
			if (!ifindex)
				return -1;
			addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
		} else if (matches(*argv, "primary_reselect") == 0) {
			NEXT_ARG();
			if (get_index(primary_reselect_tbl, *argv) < 0)
				invarg("invalid primary_reselect", *argv);
			primary_reselect = get_index(primary_reselect_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT,
				 primary_reselect);
		} else if (matches(*argv, "fail_over_mac") == 0) {
			NEXT_ARG();
			if (get_index(fail_over_mac_tbl, *argv) < 0)
				invarg("invalid fail_over_mac", *argv);
			fail_over_mac = get_index(fail_over_mac_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC,
				 fail_over_mac);
		} else if (matches(*argv, "xmit_hash_policy") == 0) {
			NEXT_ARG();
			if (get_index(xmit_hash_policy_tbl, *argv) < 0)
				invarg("invalid xmit_hash_policy", *argv);

			xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY,
				 xmit_hash_policy);
		} else if (matches(*argv, "resend_igmp") == 0) {
			NEXT_ARG();
			if (get_u32(&resend_igmp, *argv, 0))
				invarg("invalid resend_igmp", *argv);

			addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp);
		} else if (matches(*argv, "num_grat_arp") == 0 ||
			   matches(*argv, "num_unsol_na") == 0) {
			NEXT_ARG();
			if (get_u8(&num_peer_notif, *argv, 0))
				invarg("invalid num_grat_arp|num_unsol_na",
				       *argv);

			addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF,
				 num_peer_notif);
		} else if (matches(*argv, "all_slaves_active") == 0) {
			NEXT_ARG();
			if (get_u8(&all_slaves_active, *argv, 0))
				invarg("invalid all_slaves_active", *argv);

			addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE,
				 all_slaves_active);
		} else if (matches(*argv, "min_links") == 0) {
			NEXT_ARG();
			if (get_u32(&min_links, *argv, 0))
				invarg("invalid min_links", *argv);

			addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links);
		} else if (matches(*argv, "lp_interval") == 0) {
			NEXT_ARG();
			if (get_u32(&lp_interval, *argv, 0))
				invarg("invalid lp_interval", *argv);

			addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval);
		} else if (matches(*argv, "packets_per_slave") == 0) {
			NEXT_ARG();
			if (get_u32(&packets_per_slave, *argv, 0))
				invarg("invalid packets_per_slave", *argv);

			addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE,
				  packets_per_slave);
		} else if (matches(*argv, "lacp_rate") == 0) {
			NEXT_ARG();
			if (get_index(lacp_rate_tbl, *argv) < 0)
				invarg("invalid lacp_rate", *argv);

			lacp_rate = get_index(lacp_rate_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
		} else if (matches(*argv, "ad_select") == 0) {
			NEXT_ARG();
			if (get_index(ad_select_tbl, *argv) < 0)
				invarg("invalid ad_select", *argv);

			ad_select = get_index(ad_select_tbl, *argv);
			addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select);
		} else if (matches(*argv, "ad_user_port_key") == 0) {
			NEXT_ARG();
			if (get_u16(&ad_user_port_key, *argv, 0))
				invarg("invalid ad_user_port_key", *argv);

			addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY,
				  ad_user_port_key);
		} else if (matches(*argv, "ad_actor_sys_prio") == 0) {
			NEXT_ARG();
			if (get_u16(&ad_actor_sys_prio, *argv, 0))
				invarg("invalid ad_actor_sys_prio", *argv);

			addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO,
				  ad_actor_sys_prio);
		} else if (matches(*argv, "ad_actor_system") == 0) {
			int len;
			char abuf[32];

			NEXT_ARG();
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM,
				  abuf, len);
		} else if (matches(*argv, "tlb_dynamic_lb") == 0) {
			NEXT_ARG();
			if (get_u8(&tlb_dynamic_lb, *argv, 0)) {
				invarg("invalid tlb_dynamic_lb", *argv);
				return -1;
			}
			addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB,
				 tlb_dynamic_lb);
		} else if (matches(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--, argv++;
	}

	return 0;
}
Пример #16
0
static int
parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
	      struct nlmsghdr *n)
{
	struct tc_connmark sel = {};
	char **argv = *argv_p;
	int argc = *argc_p;
	int ok = 0;
	struct rtattr *tail;

	while (argc > 0) {
		if (matches(*argv, "connmark") == 0) {
			ok = 1;
			argc--;
			argv++;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			break;
		}

	}

	if (!ok) {
		explain();
		return -1;
	}

	if (argc) {
		if (matches(*argv, "zone") == 0) {
			NEXT_ARG();
			if (get_u16(&sel.zone, *argv, 10)) {
				fprintf(stderr, "simple: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
		}
	}

	parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_PIPE);

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.index, *argv, 10)) {
				fprintf(stderr, "simple: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
		}
	}

	tail = addattr_nest(n, MAX_MSG, tca_id);
	addattr_l(n, MAX_MSG, TCA_CONNMARK_PARMS, &sel, sizeof(sel));
	addattr_nest_end(n, tail);

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}
Пример #17
0
static int
parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
	      struct nlmsghdr *n)
{
	int argc = *argc_p;
	char **argv = *argv_p;
	int ok = 0;
	struct rtattr *tail;
	unsigned int tmp;
	__u16 queue_mapping, ptype;
	__u32 flags = 0, priority, mark;
	struct tc_skbedit sel = { 0 };

	if (matches(*argv, "skbedit") != 0)
		return -1;

	NEXT_ARG();

	while (argc > 0) {
		if (matches(*argv, "queue_mapping") == 0) {
			flags |= SKBEDIT_F_QUEUE_MAPPING;
			NEXT_ARG();
			if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
				fprintf(stderr, "Illegal queue_mapping\n");
				return -1;
			}
			queue_mapping = tmp;
			ok++;
		} else if (matches(*argv, "priority") == 0) {
			flags |= SKBEDIT_F_PRIORITY;
			NEXT_ARG();
			if (get_tc_classid(&priority, *argv)) {
				fprintf(stderr, "Illegal priority\n");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "mark") == 0) {
			flags |= SKBEDIT_F_MARK;
			NEXT_ARG();
			if (get_u32(&mark, *argv, 0)) {
				fprintf(stderr, "Illegal mark\n");
				return -1;
			}
			ok++;
		} else if (matches(*argv, "ptype") == 0) {

			NEXT_ARG();
			if (matches(*argv, "host") == 0) {
				ptype = PACKET_HOST;
			} else if (matches(*argv, "broadcast") == 0) {
				ptype = PACKET_BROADCAST;
			} else if (matches(*argv, "multicast") == 0) {
				ptype = PACKET_MULTICAST;
			} else if (matches(*argv, "otherhost") == 0) {
				ptype = PACKET_OTHERHOST;
			} else {
				fprintf(stderr, "Illegal ptype (%s)\n",
					*argv);
				return -1;
			}
			flags |= SKBEDIT_F_PTYPE;
			ok++;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			break;
		}
		argc--;
		argv++;
	}

	parse_action_control_dflt(&argc, &argv, &sel.action,
				  false, TC_ACT_PIPE);

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.index, *argv, 10)) {
				fprintf(stderr, "Pedit: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
			ok++;
		}
	}

	if (!ok) {
		explain();
		return -1;
	}


	tail = addattr_nest(n, MAX_MSG, tca_id);
	addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
	if (flags & SKBEDIT_F_QUEUE_MAPPING)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
			  &queue_mapping, sizeof(queue_mapping));
	if (flags & SKBEDIT_F_PRIORITY)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
			  &priority, sizeof(priority));
	if (flags & SKBEDIT_F_MARK)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
			  &mark, sizeof(mark));
	if (flags & SKBEDIT_F_PTYPE)
		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
			  &ptype, sizeof(ptype));
	addattr_nest_end(n, tail);

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}
Пример #18
0
static int iprule_modify(int cmd, int argc, char **argv)
{
	int table_ok = 0;
	struct {
		struct nlmsghdr 	n;
		struct rtmsg 		r;
		char   			buf[1024];
	} req;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_type = cmd;
	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.r.rtm_family = preferred_family;
	req.r.rtm_protocol = RTPROT_BOOT;
	req.r.rtm_scope = RT_SCOPE_UNIVERSE;
	req.r.rtm_table = 0;
	req.r.rtm_type = RTN_UNSPEC;
	req.r.rtm_flags = 0;

	if (cmd == RTM_NEWRULE) {
		req.n.nlmsg_flags |= NLM_F_CREATE|NLM_F_EXCL;
		req.r.rtm_type = RTN_UNICAST;
	}

	while (argc > 0) {
		if (strcmp(*argv, "not") == 0) {
			req.r.rtm_flags |= FIB_RULE_INVERT;
		} else if (strcmp(*argv, "from") == 0) {
			inet_prefix dst;
			NEXT_ARG();
			get_prefix(&dst, *argv, req.r.rtm_family);
			req.r.rtm_src_len = dst.bitlen;
			addattr_l(&req.n, sizeof(req), FRA_SRC, &dst.data, dst.bytelen);
		} else if (strcmp(*argv, "to") == 0) {
			inet_prefix dst;
			NEXT_ARG();
			get_prefix(&dst, *argv, req.r.rtm_family);
			req.r.rtm_dst_len = dst.bitlen;
			addattr_l(&req.n, sizeof(req), FRA_DST, &dst.data, dst.bytelen);
		} else if (matches(*argv, "preference") == 0 ||
			   matches(*argv, "order") == 0 ||
			   matches(*argv, "priority") == 0) {
			__u32 pref;
			NEXT_ARG();
			if (get_u32(&pref, *argv, 0))
				invarg("preference value is invalid\n", *argv);
			addattr32(&req.n, sizeof(req), FRA_PRIORITY, pref);
		} else if (strcmp(*argv, "tos") == 0) {
			__u32 tos;
			NEXT_ARG();
			if (rtnl_dsfield_a2n(&tos, *argv))
				invarg("TOS value is invalid\n", *argv);
			req.r.rtm_tos = tos;
		} else if (strcmp(*argv, "fwmark") == 0) {
			char *slash;
			__u32 fwmark, fwmask;
			NEXT_ARG();
			if ((slash = strchr(*argv, '/')) != NULL)
				*slash = '\0';
			if (get_u32(&fwmark, *argv, 0))
				invarg("fwmark value is invalid\n", *argv);
			addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark);
			if (slash) {
				if (get_u32(&fwmask, slash+1, 0))
					invarg("fwmask value is invalid\n", slash+1);
				addattr32(&req.n, sizeof(req), FRA_FWMASK, fwmask);
			}
		} else if (matches(*argv, "realms") == 0) {
			__u32 realm;
			NEXT_ARG();
			if (get_rt_realms(&realm, *argv))
				invarg("invalid realms\n", *argv);
			addattr32(&req.n, sizeof(req), FRA_FLOW, realm);
		} else if (matches(*argv, "table") == 0 ||
			   strcmp(*argv, "lookup") == 0) {
			__u32 tid;
			NEXT_ARG();
			if (rtnl_rttable_a2n(&tid, *argv))
				invarg("invalid table ID\n", *argv);
			if (tid < 256)
				req.r.rtm_table = tid;
			else {
				req.r.rtm_table = RT_TABLE_UNSPEC;
				addattr32(&req.n, sizeof(req), FRA_TABLE, tid);
			}
			table_ok = 1;
		} else if (strcmp(*argv, "dev") == 0 ||
			   strcmp(*argv, "iif") == 0) {
			NEXT_ARG();
			addattr_l(&req.n, sizeof(req), FRA_IFNAME, *argv, strlen(*argv)+1);
		} else if (strcmp(*argv, "nat") == 0 ||
			   matches(*argv, "map-to") == 0) {
			NEXT_ARG();
			fprintf(stderr, "Warning: route NAT is deprecated\n");
			addattr32(&req.n, sizeof(req), RTA_GATEWAY, get_addr32(*argv));
			req.r.rtm_type = RTN_NAT;
		} else {
			int type;

			if (strcmp(*argv, "type") == 0) {
				NEXT_ARG();
			}
			if (matches(*argv, "help") == 0)
				usage();
			else if (matches(*argv, "goto") == 0) {
				__u32 target;
				type = FR_ACT_GOTO;
				NEXT_ARG();
				if (get_u32(&target, *argv, 0))
					invarg("invalid target\n", *argv);
				addattr32(&req.n, sizeof(req), FRA_GOTO, target);
			} else if (matches(*argv, "nop") == 0)
				type = FR_ACT_NOP;
			else if (rtnl_rtntype_a2n(&type, *argv))
				invarg("Failed to parse rule type", *argv);
			req.r.rtm_type = type;
			table_ok = 1;
		}
		argc--;
		argv++;
	}

	if (req.r.rtm_family == AF_UNSPEC)
		req.r.rtm_family = AF_INET;

	if (!table_ok && cmd == RTM_NEWRULE)
		req.r.rtm_table = RT_TABLE_MAIN;

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		return 2;

	return 0;
}
Пример #19
0
int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
{
	struct qdisc_util *q = NULL;
	struct tc_estimator est;
	char  d[16];
	char  k[16];
	struct {
		struct nlmsghdr 	n;
		struct tcmsg 		t;
		char   			buf[TCA_BUF_MAX];
	} req;

	memset(&req, 0, sizeof(req));
	memset(&est, 0, sizeof(est));
	memset(&d, 0, sizeof(d));
	memset(&k, 0, sizeof(k));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = cmd;
	req.t.tcm_family = AF_UNSPEC;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			if (d[0])
				duparg("dev", *argv);
			strncpy(d, *argv, sizeof(d)-1);
		} else if (strcmp(*argv, "handle") == 0) {
			__u32 handle;
			if (req.t.tcm_handle)
				duparg("handle", *argv);
			NEXT_ARG();
			if (get_qdisc_handle(&handle, *argv))
				invarg(*argv, "invalid qdisc ID");
			req.t.tcm_handle = handle;
		} else if (strcmp(*argv, "root") == 0) {
			if (req.t.tcm_parent) {
				fprintf(stderr, "Error: \"root\" is duplicate parent ID\n");
				return -1;
			}
			req.t.tcm_parent = TC_H_ROOT;
#ifdef TC_H_INGRESS
		} else if (strcmp(*argv, "ingress") == 0) {
			if (req.t.tcm_parent) {
				fprintf(stderr, "Error: \"ingress\" is a duplicate parent ID\n");
				return -1;
			}
			req.t.tcm_parent = TC_H_INGRESS;
			strncpy(k, "ingress", sizeof(k)-1);
			q = get_qdisc_kind(k);
			req.t.tcm_handle = 0xffff0000;

			argc--; argv++;
			break;
#endif
		} else if (strcmp(*argv, "parent") == 0) {
			__u32 handle;
			NEXT_ARG();
			if (req.t.tcm_parent)
				duparg("parent", *argv);
			if (get_tc_classid(&handle, *argv))
				invarg(*argv, "invalid parent ID");
			req.t.tcm_parent = handle;
		} else if (matches(*argv, "estimator") == 0) {
			if (parse_estimator(&argc, &argv, &est))
				return -1;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else {
			strncpy(k, *argv, sizeof(k)-1);

			q = get_qdisc_kind(k);
			argc--; argv++;
			break;
		}
		argc--; argv++;
	}

	if (k[0])
		addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1);
	if (est.ewma_log)
		addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est));

	if (q) {
		if (!q->parse_qopt) {
			fprintf(stderr, "qdisc '%s' does not support option parsing\n", k);
			return -1;
		}
		if (q->parse_qopt(q, argc, argv, &req.n))
			return 1;
	} else {
		if (argc) {
			if (matches(*argv, "help") == 0)
				usage();

			fprintf(stderr, "Garbage instead of arguments \"%s ...\". Try \"tc qdisc help\".\n", *argv);
			return -1;
		}
	}

	if (d[0])  {
		int idx;

 		ll_init_map(&rth);

		if ((idx = ll_name_to_index(d)) == 0) {
			fprintf(stderr, "Cannot find device \"%s\"\n", d);
			return 1;
		}
		req.t.tcm_ifindex = idx;
	}

 	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		return 2;

	return 0;
}
Пример #20
0
static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
{
	struct tc_red_qopt opt;
	unsigned burst = 0;
	unsigned avpkt = 0;
	double probability = 0.02;
	__u64 rate = 0;
	int wlog;
	__u8 sbuf[256];
	__u32 max_P;
	struct rtattr *tail;

	memset(&opt, 0, sizeof(opt));

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_size(&opt.limit, *argv)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "min") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_min, *argv)) {
				fprintf(stderr, "Illegal \"min\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "max") == 0) {
			NEXT_ARG();
			if (get_size(&opt.qth_max, *argv)) {
				fprintf(stderr, "Illegal \"max\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "burst") == 0) {
			NEXT_ARG();
			if (get_unsigned(&burst, *argv, 0)) {
				fprintf(stderr, "Illegal \"burst\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "avpkt") == 0) {
			NEXT_ARG();
			if (get_size(&avpkt, *argv)) {
				fprintf(stderr, "Illegal \"avpkt\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "probability") == 0) {
			NEXT_ARG();
			if (sscanf(*argv, "%lg", &probability) != 1) {
				fprintf(stderr, "Illegal \"probability\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "bandwidth") == 0) {
			NEXT_ARG();
			if (get_rate(&rate, *argv)) {
				fprintf(stderr, "Illegal \"bandwidth\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			opt.flags |= TC_RED_ECN;
		} else if (strcmp(*argv, "harddrop") == 0) {
			opt.flags |= TC_RED_HARDDROP;
		} else if (strcmp(*argv, "adaptative") == 0) {
			opt.flags |= TC_RED_ADAPTATIVE;
		} else if (strcmp(*argv, "adaptive") == 0) {
			opt.flags |= TC_RED_ADAPTATIVE;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	if (rate == 0)
		get_rate(&rate, "10Mbit");

	if (!opt.limit || !avpkt) {
		fprintf(stderr, "RED: Required parameter (limit, avpkt) is missing\n");
		return -1;
	}
	/* Compute default min/max thresholds based on
	 * Sally Floyd's recommendations:
	 * http://www.icir.org/floyd/REDparameters.txt
	 */
	if (!opt.qth_max)
		opt.qth_max = opt.qth_min ? opt.qth_min * 3 : opt.limit / 4;
	if (!opt.qth_min)
		opt.qth_min = opt.qth_max / 3;
	if (!burst)
		burst = (2 * opt.qth_min + opt.qth_max) / (3 * avpkt);
	if ((wlog = tc_red_eval_ewma(opt.qth_min, burst, avpkt)) < 0) {
		fprintf(stderr, "RED: failed to calculate EWMA constant.\n");
		return -1;
	}
	if (wlog >= 10)
		fprintf(stderr, "RED: WARNING. Burst %d seems to be too large.\n", burst);
	opt.Wlog = wlog;
	if ((wlog = tc_red_eval_P(opt.qth_min, opt.qth_max, probability)) < 0) {
		fprintf(stderr, "RED: failed to calculate probability.\n");
		return -1;
	}
	opt.Plog = wlog;
	if ((wlog = tc_red_eval_idle_damping(opt.Wlog, avpkt, rate, sbuf)) < 0) {
		fprintf(stderr, "RED: failed to calculate idle damping table.\n");
		return -1;
	}
	opt.Scell_log = wlog;

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	addattr_l(n, 1024, TCA_RED_PARMS, &opt, sizeof(opt));
	addattr_l(n, 1024, TCA_RED_STAB, sbuf, 256);
	max_P = probability * pow(2, 32);
	addattr_l(n, 1024, TCA_RED_MAX_P, &max_P, sizeof(max_P));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}
Пример #21
0
static int parse_pedit(struct action_util *a, int *argc_p, char ***argv_p,
		       int tca_id, struct nlmsghdr *n)
{
	struct m_pedit_sel sel = {};

	int argc = *argc_p;
	char **argv = *argv_p;
	int ok = 0, iok = 0;
	struct rtattr *tail;

	while (argc > 0) {
		if (pedit_debug > 1)
			fprintf(stderr, "while pedit (%d:%s)\n", argc, *argv);
		if (matches(*argv, "pedit") == 0) {
			NEXT_ARG();
			ok++;

			if (matches(*argv, "ex") == 0) {
				if (ok > 1) {
					fprintf(stderr,
						"'ex' must be before first 'munge'\n");
					explain();
					return -1;
				}
				sel.extended = true;
				NEXT_ARG();
			}

			continue;
		} else if (matches(*argv, "help") == 0) {
			usage();
		} else if (matches(*argv, "munge") == 0) {
			if (!ok) {
				fprintf(stderr, "Bad pedit construct (%s)\n",
					*argv);
				explain();
				return -1;
			}
			NEXT_ARG();

			if (parse_munge(&argc, &argv, &sel)) {
				fprintf(stderr, "Bad pedit construct (%s)\n",
					*argv);
				explain();
				return -1;
			}
			ok++;
		} else {
			break;
		}

	}

	if (!ok) {
		explain();
		return -1;
	}

	parse_action_control_dflt(&argc, &argv, &sel.sel.action, false, TC_ACT_OK);

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.sel.index, *argv, 10)) {
				fprintf(stderr, "Pedit: Illegal \"index\"\n");
				return -1;
			}
			argc--;
			argv++;
			iok++;
		}
	}

	tail = addattr_nest(n, MAX_MSG, tca_id);
	if (!sel.extended) {
		addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS, &sel,
			  sizeof(sel.sel) +
			  sel.sel.nkeys * sizeof(struct tc_pedit_key));
	} else {
		addattr_l(n, MAX_MSG, TCA_PEDIT_PARMS_EX, &sel,
			  sizeof(sel.sel) +
			  sel.sel.nkeys * sizeof(struct tc_pedit_key));

		pedit_keys_ex_addattr(&sel, n);
	}

	addattr_nest_end(n, tail);

	*argc_p = argc;
	*argv_p = argv;
	return 0;
}
Пример #22
0
static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			   struct nlmsghdr *n, const char *dev)
{
	unsigned int limit = 0;
	unsigned int target = 0;
	unsigned int interval = 0;
	unsigned int ce_threshold = ~0U;
	int ecn = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "target") == 0) {
			NEXT_ARG();
			if (get_time(&target, *argv)) {
				fprintf(stderr, "Illegal \"target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ce_threshold") == 0) {
			NEXT_ARG();
			if (get_time(&ce_threshold, *argv)) {
				fprintf(stderr, "Illegal \"ce_threshold\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "interval") == 0) {
			NEXT_ARG();
			if (get_time(&interval, *argv)) {
				fprintf(stderr, "Illegal \"interval\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			ecn = 1;
		} else if (strcmp(*argv, "noecn") == 0) {
			ecn = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	tail = addattr_nest(n, 1024, TCA_OPTIONS);
	if (limit)
		addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
	if (interval)
		addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
	if (target)
		addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
	if (ecn != -1)
		addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn));
	if (ce_threshold != ~0U)
		addattr_l(n, 1024, TCA_CODEL_CE_THRESHOLD,
			  &ce_threshold, sizeof(ce_threshold));

	addattr_nest_end(n, tail);
	return 0;
}
Пример #23
0
static int xfrm_policy_modify(int cmd, unsigned flags, int argc, char **argv)
{
	struct rtnl_handle rth;
	struct {
		struct nlmsghdr			n;
		struct xfrm_userpolicy_info	xpinfo;
		char				buf[RTA_BUF_SIZE];
	} req;
	char *dirp = NULL;
	char *selp = NULL;
	char *ptypep = NULL;
	struct xfrm_userpolicy_type upt;
	char tmpls_buf[XFRM_TMPLS_BUF_SIZE];
	int tmpls_len = 0;

	memset(&req, 0, sizeof(req));
	memset(&upt, 0, sizeof(upt));
	memset(&tmpls_buf, 0, sizeof(tmpls_buf));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.xpinfo));
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = cmd;
	req.xpinfo.sel.family = preferred_family;

	req.xpinfo.lft.soft_byte_limit = XFRM_INF;
	req.xpinfo.lft.hard_byte_limit = XFRM_INF;
	req.xpinfo.lft.soft_packet_limit = XFRM_INF;
	req.xpinfo.lft.hard_packet_limit = XFRM_INF;

	while (argc > 0) {
		if (strcmp(*argv, "dir") == 0) {
			if (dirp)
				duparg("dir", *argv);
			dirp = *argv;

			NEXT_ARG();
			xfrm_policy_dir_parse(&req.xpinfo.dir, &argc, &argv);
		} else if (strcmp(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&req.xpinfo.index, *argv, 0))
				invarg("\"INDEX\" is invalid", *argv);
		} else if (strcmp(*argv, "ptype") == 0) {
			if (ptypep)
				duparg("ptype", *argv);
			ptypep = *argv;

			NEXT_ARG();
			xfrm_policy_ptype_parse(&upt.type, &argc, &argv);
		} else if (strcmp(*argv, "action") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "allow") == 0)
				req.xpinfo.action = XFRM_POLICY_ALLOW;
			else if (strcmp(*argv, "block") == 0)
				req.xpinfo.action = XFRM_POLICY_BLOCK;
			else
				invarg("\"action\" value is invalid\n", *argv);
		} else if (strcmp(*argv, "priority") == 0) {
			NEXT_ARG();
			if (get_u32(&req.xpinfo.priority, *argv, 0))
				invarg("\"PRIORITY\" is invalid", *argv);
		} else if (strcmp(*argv, "flag") == 0) {
			NEXT_ARG();
			xfrm_policy_flag_parse(&req.xpinfo.flags, &argc,
					       &argv);
		} else if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			xfrm_lifetime_cfg_parse(&req.xpinfo.lft, &argc, &argv);
		} else if (strcmp(*argv, "tmpl") == 0) {
			struct xfrm_user_tmpl *tmpl;

			if (tmpls_len + sizeof(*tmpl) > sizeof(tmpls_buf)) {
				fprintf(stderr, "Too many tmpls: buffer overflow\n");
				exit(1);
			}
			tmpl = (struct xfrm_user_tmpl *)((char *)tmpls_buf + tmpls_len);

			tmpl->family = preferred_family;
			tmpl->aalgos = (~(__u32)0);
			tmpl->ealgos = (~(__u32)0);
			tmpl->calgos = (~(__u32)0);

			NEXT_ARG();
			xfrm_tmpl_parse(tmpl, &argc, &argv);

			tmpls_len += sizeof(*tmpl);
		} else {
			if (selp)
				duparg("unknown", *argv);
			selp = *argv;

			xfrm_selector_parse(&req.xpinfo.sel, &argc, &argv);
			if (preferred_family == AF_UNSPEC)
				preferred_family = req.xpinfo.sel.family;
		}

		argc--; argv++;
	}

	if (!dirp) {
		fprintf(stderr, "Not enough information: \"DIR\" is required.\n");
		exit(1);
	}

	if (ptypep) {
		addattr_l(&req.n, sizeof(req), XFRMA_POLICY_TYPE,
			  (void *)&upt, sizeof(upt));
	}

	if (tmpls_len > 0) {
		addattr_l(&req.n, sizeof(req), XFRMA_TMPL,
			  (void *)tmpls_buf, tmpls_len);
	}

	if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0)
		exit(1);

	if (req.xpinfo.sel.family == AF_UNSPEC)
		req.xpinfo.sel.family = AF_INET;

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
		exit(2);

	rtnl_close(&rth);

	return 0;
}
Пример #24
0
static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
			    struct nlmsghdr *n)
{
	__u32 val;

	while (argc > 0) {
		if (matches(*argv, "forward_delay") == 0) {
			NEXT_ARG();
			if (get_u32(&val, *argv, 0))
				invarg("invalid forward_delay", *argv);

			addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val);
		} else if (matches(*argv, "hello_time") == 0) {
			NEXT_ARG();
			if (get_u32(&val, *argv, 0))
				invarg("invalid hello_time", *argv);

			addattr32(n, 1024, IFLA_BR_HELLO_TIME, val);
		} else if (matches(*argv, "max_age") == 0) {
			NEXT_ARG();
			if (get_u32(&val, *argv, 0))
				invarg("invalid max_age", *argv);

			addattr32(n, 1024, IFLA_BR_MAX_AGE, val);
		} else if (matches(*argv, "ageing_time") == 0) {
			NEXT_ARG();
			if (get_u32(&val, *argv, 0))
				invarg("invalid ageing_time", *argv);

			addattr32(n, 1024, IFLA_BR_AGEING_TIME, val);
		} else if (matches(*argv, "stp_state") == 0) {
			NEXT_ARG();
			if (get_u32(&val, *argv, 0))
				invarg("invalid stp_state", *argv);

			addattr32(n, 1024, IFLA_BR_STP_STATE, val);
		} else if (matches(*argv, "priority") == 0) {
			__u16 prio;

			NEXT_ARG();
			if (get_u16(&prio, *argv, 0))
				invarg("invalid priority", *argv);

			addattr16(n, 1024, IFLA_BR_PRIORITY, prio);
		} else if (matches(*argv, "vlan_filtering") == 0) {
			__u8 vlan_filter;

			NEXT_ARG();
			if (get_u8(&vlan_filter, *argv, 0))
				invarg("invalid vlan_filtering", *argv);

			addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter);
		} else if (matches(*argv, "vlan_protocol") == 0) {
			__u16 vlan_proto;

			NEXT_ARG();
			if (ll_proto_a2n(&vlan_proto, *argv))
				invarg("invalid vlan_protocol", *argv);

			addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto);
		} else if (matches(*argv, "group_fwd_mask") == 0) {
			__u16 fwd_mask;

			NEXT_ARG();
			if (get_u16(&fwd_mask, *argv, 0))
				invarg("invalid group_fwd_mask", *argv);

			addattr16(n, 1024, IFLA_BR_GROUP_FWD_MASK, fwd_mask);
		} else if (matches(*argv, "group_address") == 0) {
			char llabuf[32];
			int len;

			NEXT_ARG();
			len = ll_addr_a2n(llabuf, sizeof(llabuf), *argv);
			if (len < 0)
				return -1;
			addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len);
		} else if (matches(*argv, "vlan_default_pvid") == 0) {
			__u16 default_pvid;

			NEXT_ARG();
			if (get_u16(&default_pvid, *argv, 0))
				invarg("invalid vlan_default_pvid", *argv);

			addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID,
				  default_pvid);
		} else if (matches(*argv, "mcast_router") == 0) {
			__u8 mcast_router;

			NEXT_ARG();
			if (get_u8(&mcast_router, *argv, 0))
				invarg("invalid mcast_router", *argv);

			addattr8(n, 1024, IFLA_BR_MCAST_ROUTER, mcast_router);
		} else if (matches(*argv, "mcast_snooping") == 0) {
			__u8 mcast_snoop;

			NEXT_ARG();
			if (get_u8(&mcast_snoop, *argv, 0))
				invarg("invalid mcast_snooping", *argv);

			addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop);
		} else if (matches(*argv, "mcast_query_use_ifaddr") == 0) {
			__u8 mcast_qui;

			NEXT_ARG();
			if (get_u8(&mcast_qui, *argv, 0))
				invarg("invalid mcast_query_use_ifaddr",
				       *argv);

			addattr8(n, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR,
				 mcast_qui);
		} else if (matches(*argv, "mcast_querier") == 0) {
			__u8 mcast_querier;

			NEXT_ARG();
			if (get_u8(&mcast_querier, *argv, 0))
				invarg("invalid mcast_querier", *argv);

			addattr8(n, 1024, IFLA_BR_MCAST_QUERIER, mcast_querier);
		} else if (matches(*argv, "mcast_hash_elasticity") == 0) {
			__u32 mcast_hash_el;

			NEXT_ARG();
			if (get_u32(&mcast_hash_el, *argv, 0))
				invarg("invalid mcast_hash_elasticity",
				       *argv);

			addattr32(n, 1024, IFLA_BR_MCAST_HASH_ELASTICITY,
				  mcast_hash_el);
		} else if (matches(*argv, "mcast_hash_max") == 0) {
			__u32 mcast_hash_max;

			NEXT_ARG();
			if (get_u32(&mcast_hash_max, *argv, 0))
				invarg("invalid mcast_hash_max", *argv);

			addattr32(n, 1024, IFLA_BR_MCAST_HASH_MAX,
				  mcast_hash_max);
		} else if (matches(*argv, "mcast_last_member_count") == 0) {
			__u32 mcast_lmc;

			NEXT_ARG();
			if (get_u32(&mcast_lmc, *argv, 0))
				invarg("invalid mcast_last_member_count",
				       *argv);

			addattr32(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT,
				  mcast_lmc);
		} else if (matches(*argv, "mcast_startup_query_count") == 0) {
			__u32 mcast_sqc;

			NEXT_ARG();
			if (get_u32(&mcast_sqc, *argv, 0))
				invarg("invalid mcast_startup_query_count",
				       *argv);

			addattr32(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT,
				  mcast_sqc);
		} else if (matches(*argv, "mcast_last_member_interval") == 0) {
			__u64 mcast_last_member_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_last_member_intvl, *argv, 0))
				invarg("invalid mcast_last_member_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL,
				  mcast_last_member_intvl);
		} else if (matches(*argv, "mcast_membership_interval") == 0) {
			__u64 mcast_membership_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_membership_intvl, *argv, 0))
				invarg("invalid mcast_membership_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL,
				  mcast_membership_intvl);
		} else if (matches(*argv, "mcast_querier_interval") == 0) {
			__u64 mcast_querier_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_querier_intvl, *argv, 0))
				invarg("invalid mcast_querier_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_QUERIER_INTVL,
				  mcast_querier_intvl);
		} else if (matches(*argv, "mcast_query_interval") == 0) {
			__u64 mcast_query_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_query_intvl, *argv, 0))
				invarg("invalid mcast_query_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_QUERY_INTVL,
				  mcast_query_intvl);
		} else if (!matches(*argv, "mcast_query_response_interval")) {
			__u64 mcast_query_resp_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_query_resp_intvl, *argv, 0))
				invarg("invalid mcast_query_response_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
				  mcast_query_resp_intvl);
		} else if (!matches(*argv, "mcast_startup_query_interval")) {
			__u64 mcast_startup_query_intvl;

			NEXT_ARG();
			if (get_u64(&mcast_startup_query_intvl, *argv, 0))
				invarg("invalid mcast_startup_query_interval",
				       *argv);

			addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
				  mcast_startup_query_intvl);
		} else if (matches(*argv, "nf_call_iptables") == 0) {
			__u8 nf_call_ipt;

			NEXT_ARG();
			if (get_u8(&nf_call_ipt, *argv, 0))
				invarg("invalid nf_call_iptables", *argv);

			addattr8(n, 1024, IFLA_BR_NF_CALL_IPTABLES,
				 nf_call_ipt);
		} else if (matches(*argv, "nf_call_ip6tables") == 0) {
			__u8 nf_call_ip6t;

			NEXT_ARG();
			if (get_u8(&nf_call_ip6t, *argv, 0))
				invarg("invalid nf_call_ip6tables", *argv);

			addattr8(n, 1024, IFLA_BR_NF_CALL_IP6TABLES,
				 nf_call_ip6t);
		} else if (matches(*argv, "nf_call_arptables") == 0) {
			__u8 nf_call_arpt;

			NEXT_ARG();
			if (get_u8(&nf_call_arpt, *argv, 0))
				invarg("invalid nf_call_arptables", *argv);

			addattr8(n, 1024, IFLA_BR_NF_CALL_ARPTABLES,
				 nf_call_arpt);
		} else if (matches(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--, argv++;
	}

	return 0;
}
static int
parse_csum(struct action_util *a, int *argc_p,
	   char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	struct tc_csum sel;

	int argc = *argc_p;
	char **argv = *argv_p;
	int ok = 0;
	struct rtattr *tail;

	memset(&sel, 0, sizeof(sel));

	while (argc > 0) {
		if (matches(*argv, "csum") == 0) {
			NEXT_ARG();
			if (parse_csum_args(&argc, &argv, &sel)) {
				fprintf(stderr, "Illegal csum construct (%s)\n",
					*argv);
				explain();
				return -1;
			}
			ok++;
			continue;
		} else if (matches(*argv, "help") == 0) {
			usage();
		}
		else {
			break;
		}
	}

	if (!ok) {
		explain();
		return -1;
	}

	if (sel.update_flags == 0) {
		fprintf(stderr, "Illegal csum construct, empty <UPDATE> list\n");
		return -1;
	}

	if (argc) {
		if (matches(*argv, "reclassify") == 0) {
			sel.action = TC_ACT_RECLASSIFY;
			argc--;
			argv++;
		} else if (matches(*argv, "pipe") == 0) {
			sel.action = TC_ACT_PIPE;
			argc--;
			argv++;
		} else if (matches(*argv, "drop") == 0 ||
			matches(*argv, "shot") == 0) {
			sel.action = TC_ACT_SHOT;
			argc--;
			argv++;
		} else if (matches(*argv, "continue") == 0) {
			sel.action = TC_ACT_UNSPEC;
			argc--;
			argv++;
		} else if (matches(*argv, "pass") == 0) {
			sel.action = TC_ACT_OK;
			argc--;
			argv++;
		}
	}

	if (argc) {
		if (matches(*argv, "index") == 0) {
			NEXT_ARG();
			if (get_u32(&sel.index, *argv, 10)) {
				fprintf(stderr, "Illegal \"index\" (%s) <csum>\n",
					*argv);
				return -1;
			}
			argc--;
			argv++;
		}
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
	addattr_l(n, MAX_MSG, TCA_CSUM_PARMS, &sel, sizeof(sel));
	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;

	*argc_p = argc;
	*argv_p = argv;

	return 0;
}
Пример #26
0
int
netlink_link_add_vmac(vrrp_rt *vrrp)
{
    struct rtattr *linkinfo;
    interface *ifp;
    char ifname[IFNAMSIZ];
    struct {
        struct nlmsghdr n;
        struct ifinfomsg ifi;
        char buf[256];
    } req;

    if (!vrrp->ifp)
        return -1;

    memset(&req, 0, sizeof (req));
    memset(ifname, 0, IFNAMSIZ);
    strncpy(ifname, vrrp->vmac_ifname, IFNAMSIZ - 1);

    /*
     * Check to see if this vmac interface was created
     * by a previous instance.
     */
    if (reload && (ifp = if_get_by_ifname(ifname))) {
        vrrp->xmit_ifp = ifp;
        /* Save ifindex for use on delete */
        vrrp->vmac_ifindex = IF_INDEX(vrrp->xmit_ifp);
        vrrp->vmac |= 2;
        return 1;
    }

    req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg));
    req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
    req.n.nlmsg_type = RTM_NEWLINK;
    req.ifi.ifi_family = AF_INET;

    /* macvlan settings */
    linkinfo = NLMSG_TAIL(&req.n);
    addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
    addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind));
    linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
    addattr_l(&req.n, sizeof(req), IFLA_LINK, &IF_INDEX(vrrp->ifp), sizeof(uint32_t));
    addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname));

    if (netlink_talk(&nl_cmd, &req.n) < 0)
        return -1;

    /*
     * Update interface queue and vrrp instance interface binding.
     * bring it UP !
     */
    netlink_interface_lookup();
    ifp = if_get_by_ifname(ifname);
    if (!ifp)
        return -1;
    vrrp->xmit_ifp = ifp;
    vrrp->vmac_ifindex = IF_INDEX(vrrp->xmit_ifp); /* For use on delete */
    vrrp->vmac |= 2;
    netlink_link_setlladdr(vrrp);
    vyatta_if_setup(ifname);
    netlink_link_up(vrrp);
    netlink_link_setmode(vrrp);

    return 1;
}
Пример #27
0
static int parse_ipt(struct action_util *a, int *argc_p,
		     char ***argv_p, int tca_id, struct nlmsghdr *n)
{
	struct xtables_target *m = NULL;
	struct ipt_entry fw;
	struct rtattr *tail;
	int c;
	int rargc = *argc_p;
	char **argv = *argv_p;
	int argc = 0, iargc = 0;
	char k[FILTER_NAMESZ];
	int size = 0;
	int iok = 0, ok = 0;
	__u32 hook = 0, index = 0;

	set_lib_dir();

	{
		int i;

		for (i = 0; i < rargc; i++) {
			if (NULL == argv[i] || 0 == strcmp(argv[i], "action")) {
				break;
			}
		}
		iargc = argc = i;
	}

	if (argc <= 2) {
		fprintf(stderr, "bad arguments to ipt %d vs %d\n", argc, rargc);
		return -1;
	}

	while (1) {
		c = getopt_long(argc, argv, "j:", opts, NULL);
		if (c == -1)
			break;
		switch (c) {
		case 'j':
			m = find_target(optarg, TRY_LOAD);
			if (m != NULL) {

				if (build_st(m, NULL) < 0) {
					printf(" %s error\n", m->name);
					return -1;
				}
				opts =
				    merge_options(opts, m->extra_opts,
						  &m->option_offset);
			} else {
				fprintf(stderr, " failed to find target %s\n\n", optarg);
				return -1;
			}
			ok++;
			break;

		default:
			memset(&fw, 0, sizeof(fw));
			if (m) {
				m->parse(c - m->option_offset, argv, 0,
					 &m->tflags, NULL, &m->t);
			} else {
				fprintf(stderr, " failed to find target %s\n\n", optarg);
				return -1;

			}
			ok++;
			break;

		}
	}

	if (iargc > optind) {
		if (matches(argv[optind], "index") == 0) {
			if (get_u32(&index, argv[optind + 1], 10)) {
				fprintf(stderr, "Illegal \"index\"\n");
				free_opts(opts);
				return -1;
			}
			iok++;

			optind += 2;
		}
	}

	if (!ok && !iok) {
		fprintf(stderr, " ipt Parser BAD!! (%s)\n", *argv);
		return -1;
	}

	/* check that we passed the correct parameters to the target */
	if (m)
		m->final_check(m->tflags);

	{
		struct tcmsg *t = NLMSG_DATA(n);

		if (t->tcm_parent != TC_H_ROOT
		    && t->tcm_parent == TC_H_MAJ(TC_H_INGRESS)) {
			hook = NF_IP_PRE_ROUTING;
		} else {
			hook = NF_IP_POST_ROUTING;
		}
	}

	tail = addattr_nest(n, MAX_MSG, tca_id);
	fprintf(stdout, "tablename: %s hook: %s\n ", tname, ipthooks[hook]);
	fprintf(stdout, "\ttarget: ");

	if (m)
		m->print(NULL, m->t, 0);
	fprintf(stdout, " index %d\n", index);

	if (strlen(tname) > 16) {
		size = 16;
		k[15] = 0;
	} else {
		size = 1 + strlen(tname);
	}
	strncpy(k, tname, size);

	addattr_l(n, MAX_MSG, TCA_IPT_TABLE, k, size);
	addattr_l(n, MAX_MSG, TCA_IPT_HOOK, &hook, 4);
	addattr_l(n, MAX_MSG, TCA_IPT_INDEX, &index, 4);
	if (m)
		addattr_l(n, MAX_MSG, TCA_IPT_TARG, m->t, m->t->u.target_size);
	addattr_nest_end(n, tail);

	argc -= optind;
	argv += optind;
	*argc_p = rargc - iargc;
	*argv_p = argv;

	optind = 0;
	free_opts(opts);
	/* Clear flags if target will be used again */
        m->tflags = 0;
        m->used = 0;
	/* Free allocated memory */
	if (m->t)
	    free(m->t);


	return 0;

}
Пример #28
0
static int mdb_modify(int cmd, int flags, int argc, char **argv)
{
	struct {
		struct nlmsghdr 	n;
		struct br_port_msg	bpm;
		char   			buf[1024];
	} req;
	struct br_mdb_entry entry;
	char *d = NULL, *p = NULL, *grp = NULL;

	memset(&req, 0, sizeof(req));
	memset(&entry, 0, sizeof(entry));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_port_msg));
	req.n.nlmsg_flags = NLM_F_REQUEST|flags;
	req.n.nlmsg_type = cmd;
	req.bpm.family = PF_BRIDGE;

	while (argc > 0) {
		if (strcmp(*argv, "dev") == 0) {
			NEXT_ARG();
			d = *argv;
		} else if (strcmp(*argv, "grp") == 0) {
			NEXT_ARG();
			grp = *argv;
		} else if (strcmp(*argv, "port") == 0) {
			NEXT_ARG();
			p = *argv;
		} else if (strcmp(*argv, "permanent") == 0) {
			if (cmd == RTM_NEWMDB)
				entry.state |= MDB_PERMANENT;
		} else if (strcmp(*argv, "temp") == 0) {
			;/* nothing */
		} else {
			if (matches(*argv, "help") == 0)
				usage();
		}
		argc--; argv++;
	}

	if (d == NULL || grp == NULL || p == NULL) {
		fprintf(stderr, "Device, group address and port name are required arguments.\n");
		exit(-1);
	}

	req.bpm.ifindex = ll_name_to_index(d);
	if (req.bpm.ifindex == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", d);
		return -1;
	}

	entry.ifindex = ll_name_to_index(p);
	if (entry.ifindex == 0) {
		fprintf(stderr, "Cannot find device \"%s\"\n", p);
		return -1;
	}

	if (!inet_pton(AF_INET, grp, &entry.addr.u.ip4)) {
		if (!inet_pton(AF_INET6, grp, &entry.addr.u.ip6)) {
			fprintf(stderr, "Invalid address \"%s\"\n", grp);
			return -1;
		} else
			entry.addr.proto = htons(ETH_P_IPV6);
	} else
		entry.addr.proto = htons(ETH_P_IP);

	addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry));

	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
		exit(2);

	return 0;
}
Пример #29
0
static int gre_parse_opt(struct link_util *lu, int argc, char **argv,
			 struct nlmsghdr *n)
{
	struct {
		struct nlmsghdr n;
		struct ifinfomsg i;
		char buf[1024];
	} req;
	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
	struct rtattr *tb[IFLA_MAX + 1];
	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
	__u16 iflags = 0;
	__u16 oflags = 0;
	unsigned ikey = 0;
	unsigned okey = 0;
	struct in6_addr raddr = IN6ADDR_ANY_INIT;
	struct in6_addr laddr = IN6ADDR_ANY_INIT;
	unsigned link = 0;
	unsigned flowinfo = 0;
	unsigned flags = 0;
	__u8 hop_limit = DEFAULT_TNL_HOP_LIMIT;
	__u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
	int len;

	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
		memset(&req, 0, sizeof(req));

		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
		req.n.nlmsg_flags = NLM_F_REQUEST;
		req.n.nlmsg_type = RTM_GETLINK;
		req.i.ifi_family = preferred_family;
		req.i.ifi_index = ifi->ifi_index;

		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
get_failed:
			fprintf(stderr,
				"Failed to get existing tunnel info.\n");
			return -1;
		}

		len = req.n.nlmsg_len;
		len -= NLMSG_LENGTH(sizeof(*ifi));
		if (len < 0)
			goto get_failed;

		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);

		if (!tb[IFLA_LINKINFO])
			goto get_failed;

		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);

		if (!linkinfo[IFLA_INFO_DATA])
			goto get_failed;

		parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
				    linkinfo[IFLA_INFO_DATA]);

		if (greinfo[IFLA_GRE_IKEY])
			ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);

		if (greinfo[IFLA_GRE_OKEY])
			okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]);

		if (greinfo[IFLA_GRE_IFLAGS])
			iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]);

		if (greinfo[IFLA_GRE_OFLAGS])
			oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);

		if (greinfo[IFLA_GRE_LOCAL])
			memcpy(&laddr, RTA_DATA(greinfo[IFLA_GRE_LOCAL]), sizeof(laddr));

		if (greinfo[IFLA_GRE_REMOTE])
			memcpy(&raddr, RTA_DATA(greinfo[IFLA_GRE_REMOTE]), sizeof(raddr));

		if (greinfo[IFLA_GRE_TTL])
			hop_limit = rta_getattr_u8(greinfo[IFLA_GRE_TTL]);

		if (greinfo[IFLA_GRE_LINK])
			link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]);

		if (greinfo[IFLA_GRE_ENCAP_LIMIT])
			encap_limit = rta_getattr_u8(greinfo[IFLA_GRE_ENCAP_LIMIT]);

		if (greinfo[IFLA_GRE_FLOWINFO])
			flowinfo = rta_getattr_u32(greinfo[IFLA_GRE_FLOWINFO]);

		if (greinfo[IFLA_GRE_FLAGS])
			flags = rta_getattr_u32(greinfo[IFLA_GRE_FLAGS]);
	}

	while (argc > 0) {
		if (!matches(*argv, "key")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0) < 0) {
					fprintf(stderr,
						"Invalid value for \"key\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}

			ikey = okey = uval;
		} else if (!matches(*argv, "ikey")) {
			unsigned uval;

			NEXT_ARG();
			iflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value of \"ikey\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}
			ikey = uval;
		} else if (!matches(*argv, "okey")) {
			unsigned uval;

			NEXT_ARG();
			oflags |= GRE_KEY;
			if (strchr(*argv, '.'))
				uval = get_addr32(*argv);
			else {
				if (get_unsigned(&uval, *argv, 0)<0) {
					fprintf(stderr, "invalid value of \"okey\"\n");
					exit(-1);
				}
				uval = htonl(uval);
			}
			okey = uval;
		} else if (!matches(*argv, "seq")) {
			iflags |= GRE_SEQ;
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "iseq")) {
			iflags |= GRE_SEQ;
		} else if (!matches(*argv, "oseq")) {
			oflags |= GRE_SEQ;
		} else if (!matches(*argv, "csum")) {
			iflags |= GRE_CSUM;
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "icsum")) {
			iflags |= GRE_CSUM;
		} else if (!matches(*argv, "ocsum")) {
			oflags |= GRE_CSUM;
		} else if (!matches(*argv, "remote")) {
			inet_prefix addr;
			NEXT_ARG();
			get_prefix(&addr, *argv, preferred_family);
			if (addr.family == AF_UNSPEC)
				invarg("\"remote\" address family is AF_UNSPEC", *argv);
			memcpy(&raddr, &addr.data, sizeof(raddr));
		} else if (!matches(*argv, "local")) {
			inet_prefix addr;
			NEXT_ARG();
			get_prefix(&addr, *argv, preferred_family);
			if (addr.family == AF_UNSPEC)
				invarg("\"local\" address family is AF_UNSPEC", *argv);
			memcpy(&laddr, &addr.data, sizeof(laddr));
		} else if (!matches(*argv, "dev")) {
			NEXT_ARG();
			link = if_nametoindex(*argv);
			if (link == 0) {
				fprintf(stderr, "Cannot find device \"%s\"\n",
					*argv);
				exit(-1);
			}
		} else if (!matches(*argv, "ttl") ||
			   !matches(*argv, "hoplimit")) {
			__u8 uval;
			NEXT_ARG();
			if (get_u8(&uval, *argv, 0))
				invarg("invalid TTL", *argv);
			hop_limit = uval;
		} else if (!matches(*argv, "tos") ||
			   !matches(*argv, "tclass") ||
			   !matches(*argv, "dsfield")) {
			__u8 uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") == 0)
				flags |= IP6_TNL_F_USE_ORIG_TCLASS;
			else {
				if (get_u8(&uval, *argv, 16))
					invarg("invalid TClass", *argv);
				flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS;
				flags &= ~IP6_TNL_F_USE_ORIG_TCLASS;
			}
		} else if (strcmp(*argv, "flowlabel") == 0 ||
			   strcmp(*argv, "fl") == 0) {
			__u32 uval;
			NEXT_ARG();
			if (strcmp(*argv, "inherit") == 0)
				flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
			else {
				if (get_u32(&uval, *argv, 16))
					invarg("invalid Flowlabel", *argv);
				if (uval > 0xFFFFF)
					invarg("invalid Flowlabel", *argv);
				flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL;
				flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
			}
		} else if (strcmp(*argv, "dscp") == 0) {
			NEXT_ARG();
			if (strcmp(*argv, "inherit") != 0)
				invarg("not inherit", *argv);
			flags |= IP6_TNL_F_RCV_DSCP_COPY;
		} else
			usage();
		argc--; argv++;
	}

	addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
	addattr32(n, 1024, IFLA_GRE_OKEY, okey);
	addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
	addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
	addattr_l(n, 1024, IFLA_GRE_LOCAL, &laddr, sizeof(laddr));
	addattr_l(n, 1024, IFLA_GRE_REMOTE, &raddr, sizeof(raddr));
	if (link)
		addattr32(n, 1024, IFLA_GRE_LINK, link);
	addattr_l(n, 1024, IFLA_GRE_TTL, &hop_limit, 1);
	addattr_l(n, 1024, IFLA_GRE_ENCAP_LIMIT, &encap_limit, 1);
	addattr_l(n, 1024, IFLA_GRE_FLOWINFO, &flowinfo, 4);
	addattr_l(n, 1024, IFLA_GRE_FLAGS, &flowinfo, 4);

	return 0;
}
Пример #30
0
static int fq_pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			      struct nlmsghdr *n)
{
	unsigned limit = 0;
	unsigned flows = 0;
	unsigned target = 0;
	unsigned quantum = 0;
	unsigned tupdate = 0;
	unsigned alpha   = 0;
	unsigned beta    = 0;
	int ecn = -1;
	int bytemode = -1;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "flows") == 0) {
			NEXT_ARG();
			if (get_unsigned(&flows, *argv, 0)) {
				fprintf(stderr, "Illegal \"flows\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "quantum") == 0) {
			NEXT_ARG();
			if (get_unsigned(&quantum, *argv, 0)) {
				fprintf(stderr, "Illegal \"quantum\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "target") == 0) {
			NEXT_ARG();
			if (get_time(&target, *argv)) {
				fprintf(stderr, "Illegal \"target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "tupdate") == 0) {
			NEXT_ARG();
			if (get_time(&tupdate, *argv)) {
				fprintf(stderr, "Illegal \"tupdate\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "alpha") == 0) {
			NEXT_ARG();
			if (get_unsigned(&alpha, *argv, 0) ||
			    (alpha > ALPHA_MAX) || (alpha < ALPHA_MIN)) {
				fprintf(stderr, "Illegal \"alpha\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "beta") == 0) {
			NEXT_ARG();
			if (get_unsigned(&beta, *argv, 0) ||
			    (beta > BETA_MAX) || (beta < BETA_MIN)) {
				fprintf(stderr, "Illegal \"beta\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ecn") == 0) {
			ecn = 1;
		} else if (strcmp(*argv, "noecn") == 0) {
			ecn = 0;
		} else if (strcmp(*argv, "bytemode") == 0) {
			bytemode = 1;
		} else if (strcmp(*argv, "nobytemode") == 0) {
			bytemode = 0;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "What is \"%s\"?\n", *argv);
			explain();
			return -1;
		}
		argc--;
		argv++;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	if (limit)
		addattr_l(n, 1024, TCA_FQ_PIE_LIMIT, &limit, sizeof(limit));
	if (flows)
		addattr_l(n, 1024, TCA_FQ_PIE_FLOWS, &flows, sizeof(flows));
	if (quantum)
		addattr_l(n, 1024, TCA_FQ_PIE_QUANTUM, &quantum, sizeof(quantum));
	if (tupdate)
		addattr_l(n, 1024, TCA_FQ_PIE_TUPDATE, &tupdate, sizeof(tupdate));
	if (target)
		addattr_l(n, 1024, TCA_FQ_PIE_TARGET, &target, sizeof(target));
	if (alpha)
		addattr_l(n, 1024, TCA_FQ_PIE_ALPHA, &alpha, sizeof(alpha));
	if (beta)
		addattr_l(n, 1024, TCA_FQ_PIE_BETA, &beta, sizeof(beta));
	if (ecn != -1)
		addattr_l(n, 1024, TCA_FQ_PIE_ECN, &ecn, sizeof(ecn));
	if (bytemode != -1)
		addattr_l(n, 1024, TCA_FQ_PIE_BYTEMODE, &bytemode,
			  sizeof(bytemode));
	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}