18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
28c2ecf20Sopenharmony_ci/* Copyright (C) 2020 Facebook, Inc. */
38c2ecf20Sopenharmony_ci#include <stdlib.h>
48c2ecf20Sopenharmony_ci#include <errno.h>
58c2ecf20Sopenharmony_ci#include "testing_helpers.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciint parse_num_list(const char *s, bool **num_set, int *num_set_len)
88c2ecf20Sopenharmony_ci{
98c2ecf20Sopenharmony_ci	int i, set_len = 0, new_len, num, start = 0, end = -1;
108c2ecf20Sopenharmony_ci	bool *set = NULL, *tmp, parsing_end = false;
118c2ecf20Sopenharmony_ci	char *next;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	while (s[0]) {
148c2ecf20Sopenharmony_ci		errno = 0;
158c2ecf20Sopenharmony_ci		num = strtol(s, &next, 10);
168c2ecf20Sopenharmony_ci		if (errno)
178c2ecf20Sopenharmony_ci			return -errno;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci		if (parsing_end)
208c2ecf20Sopenharmony_ci			end = num;
218c2ecf20Sopenharmony_ci		else
228c2ecf20Sopenharmony_ci			start = num;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci		if (!parsing_end && *next == '-') {
258c2ecf20Sopenharmony_ci			s = next + 1;
268c2ecf20Sopenharmony_ci			parsing_end = true;
278c2ecf20Sopenharmony_ci			continue;
288c2ecf20Sopenharmony_ci		} else if (*next == ',') {
298c2ecf20Sopenharmony_ci			parsing_end = false;
308c2ecf20Sopenharmony_ci			s = next + 1;
318c2ecf20Sopenharmony_ci			end = num;
328c2ecf20Sopenharmony_ci		} else if (*next == '\0') {
338c2ecf20Sopenharmony_ci			parsing_end = false;
348c2ecf20Sopenharmony_ci			s = next;
358c2ecf20Sopenharmony_ci			end = num;
368c2ecf20Sopenharmony_ci		} else {
378c2ecf20Sopenharmony_ci			return -EINVAL;
388c2ecf20Sopenharmony_ci		}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci		if (start > end)
418c2ecf20Sopenharmony_ci			return -EINVAL;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci		if (end + 1 > set_len) {
448c2ecf20Sopenharmony_ci			new_len = end + 1;
458c2ecf20Sopenharmony_ci			tmp = realloc(set, new_len);
468c2ecf20Sopenharmony_ci			if (!tmp) {
478c2ecf20Sopenharmony_ci				free(set);
488c2ecf20Sopenharmony_ci				return -ENOMEM;
498c2ecf20Sopenharmony_ci			}
508c2ecf20Sopenharmony_ci			for (i = set_len; i < start; i++)
518c2ecf20Sopenharmony_ci				tmp[i] = false;
528c2ecf20Sopenharmony_ci			set = tmp;
538c2ecf20Sopenharmony_ci			set_len = new_len;
548c2ecf20Sopenharmony_ci		}
558c2ecf20Sopenharmony_ci		for (i = start; i <= end; i++)
568c2ecf20Sopenharmony_ci			set[i] = true;
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	if (!set)
608c2ecf20Sopenharmony_ci		return -EINVAL;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	*num_set = set;
638c2ecf20Sopenharmony_ci	*num_set_len = set_len;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	return 0;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci__u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	__u32 info_len = sizeof(*info);
718c2ecf20Sopenharmony_ci	int err;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	memset(info, 0, sizeof(*info));
748c2ecf20Sopenharmony_ci	err = bpf_obj_get_info_by_fd(bpf_link__fd(link), info, &info_len);
758c2ecf20Sopenharmony_ci	if (err) {
768c2ecf20Sopenharmony_ci		printf("failed to get link info: %d\n", -errno);
778c2ecf20Sopenharmony_ci		return 0;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci	return info->prog_id;
808c2ecf20Sopenharmony_ci}
81