예제 #1
0
static int
rtnetlink_rcv_msg(struct sk_buf *skb, struct nlmsghdr *nlh) {

//    struct net *net = sock_net(skb->sk);
    rtnl_doit_func doit;
    int sz_idx, kind;
    int family;
    int type;
    int err;

    type = nlh->nlmsg_type;
    if (type > RTM_MAX) {
        RTE_LOG(ERR, QoS, "Operation not supported!\n");
        return -EOPNOTSUPP;
    }

    type -= RTM_BASE;

    /* All the messages must have at least 1 byte length */
    if (nlmsg_len(nlh) < (int)sizeof(struct rtgenmsg)) {
        RTE_LOG(ERR, QoS, "Message is too short!\n");
        return 0;
    }

    family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
    sz_idx = type>>2;
    kind = type&3;

//    if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN))
//           return -EPERM;
//    if (kind != 2) {
//       RTE_LOG(ERR, QoS, "Operation is not permitted!\n");
//       return -EPERM;
//   }

    if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
//            struct sock *rtnl;
           rtnl_dumpit_func dumpit;
           rtnl_calcit_func calcit;
           u16 min_dump_alloc = 0;

           dumpit = rtnl_get_dumpit(family, type);
           if (dumpit == NULL)
                   return -EOPNOTSUPP;
           calcit = rtnl_get_calcit(family, type);
           if (calcit)
                   min_dump_alloc = calcit(skb, nlh);

//           __rtnl_unlock();
//           rtnl = net->rtnl;
           {
                   struct netlink_dump_control c = {
                           .dump           = dumpit,
                           .min_dump_alloc = min_dump_alloc,
                   };
                   err = netlink_dump_start(skb, nlh, &c);
           }
//            rtnl_lock();
           return err;
    }
예제 #2
0
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	rtnl_doit_func doit;
	int sz_idx, kind;
	int min_len;
	int family;
	int type;
	int err;

	type = nlh->nlmsg_type;
	if (type > RTM_MAX)
		return -EOPNOTSUPP;

	type -= RTM_BASE;

	/* All the messages must have at least 1 byte length */
	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
		return 0;

	family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
	if (family >= NPROTO)
		return -EAFNOSUPPORT;

	sz_idx = type>>2;
	kind = type&3;

	if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN))
		return -EPERM;

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		rtnl_dumpit_func dumpit;

		dumpit = rtnl_get_dumpit(family, type);
		if (dumpit == NULL)
			return -EOPNOTSUPP;

		__rtnl_unlock();
		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
		rtnl_lock();
		return err;
	}

	memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));

	min_len = rtm_min[sz_idx];
	if (nlh->nlmsg_len < min_len)
		return -EINVAL;

	if (nlh->nlmsg_len > min_len) {
		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
		struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len);

		while (RTA_OK(attr, attrlen)) {
			unsigned flavor = attr->rta_type;
			if (flavor) {
				if (flavor > rta_max[sz_idx])
					return -EINVAL;
				rta_buf[flavor-1] = attr;
			}
			attr = RTA_NEXT(attr, attrlen);
		}
	}

	doit = rtnl_get_doit(family, type);
	if (doit == NULL)
		return -EOPNOTSUPP;

	return doit(skb, nlh, (void *)&rta_buf[0]);
}