typedef int (*rtnl_filter_t)(const struct sockaddr_nl *,
struct nlmsghdr *n, void *);
+
+struct rtnl_dump_filter_arg
+{
+ rtnl_filter_t filter;
+ void *arg1;
+ rtnl_filter_t junk;
+ void *arg2;
+};
+
+extern int rtnl_dump_filter_l(struct rtnl_handle *rth,
+ const struct rtnl_dump_filter_arg *arg);
extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter,
void *arg1,
rtnl_filter_t junk,
void *arg2);
+
extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
unsigned groups, struct nlmsghdr *answer,
rtnl_filter_t junk,
return 0;
}
+int print_addrinfo_primary(const struct sockaddr_nl *who, struct nlmsghdr *n,
+ void *arg)
+{
+ struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+ if (!ifa->ifa_flags & IFA_F_SECONDARY)
+ return 0;
+
+ return print_addrinfo(who, n, arg);
+}
+
+int print_addrinfo_secondary(const struct sockaddr_nl *who, struct nlmsghdr *n,
+ void *arg)
+{
+ struct ifaddrmsg *ifa = NLMSG_DATA(n);
+
+ if (ifa->ifa_flags & IFA_F_SECONDARY)
+ return 0;
+
+ return print_addrinfo(who, n, arg);
+}
struct nlmsg_list
{
filter.flushe = sizeof(flushb);
while (round < MAX_ROUNDS) {
+ const struct rtnl_dump_filter_arg a[3] = {
+ {
+ .filter = print_addrinfo_secondary,
+ .arg1 = stdout,
+ .junk = NULL,
+ .arg2 = NULL
+ },
+ {
+ .filter = print_addrinfo_primary,
+ .arg1 = stdout,
+ .junk = NULL,
+ .arg2 = NULL
+ },
+ {
+ .filter = NULL,
+ .arg1 = NULL,
+ .junk = NULL,
+ .arg2 = NULL
+ },
+ };
if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
perror("Cannot send dump request");
exit(1);
}
filter.flushed = 0;
- if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
+ if (rtnl_dump_filter_l(&rth, a) < 0) {
fprintf(stderr, "Flush terminated\n");
exit(1);
}
return sendmsg(rth->fd, &msg, 0);
}
-int rtnl_dump_filter(struct rtnl_handle *rth,
- rtnl_filter_t filter,
- void *arg1,
- rtnl_filter_t junk,
- void *arg2)
+int rtnl_dump_filter_l(struct rtnl_handle *rth,
+ const struct rtnl_dump_filter_arg *arg)
{
struct sockaddr_nl nladdr;
struct iovec iov;
iov.iov_base = buf;
while (1) {
int status;
- struct nlmsghdr *h;
+ const struct rtnl_dump_filter_arg *a;
iov.iov_len = sizeof(buf);
status = recvmsg(rth->fd, &msg, 0);
return -1;
}
- h = (struct nlmsghdr*)buf;
- while (NLMSG_OK(h, status)) {
- int err;
+ for (a = arg; a->filter; a++) {
+ struct nlmsghdr *h = (struct nlmsghdr*)buf;
- if (nladdr.nl_pid != 0 ||
- h->nlmsg_pid != rth->local.nl_pid ||
- h->nlmsg_seq != rth->dump) {
- if (junk) {
- err = junk(&nladdr, h, arg2);
- if (err < 0)
- return err;
+ while (NLMSG_OK(h, status)) {
+ int err;
+
+ if (nladdr.nl_pid != 0 ||
+ h->nlmsg_pid != rth->local.nl_pid ||
+ h->nlmsg_seq != rth->dump) {
+ if (a->junk) {
+ err = a->junk(&nladdr, h,
+ a->arg2);
+ if (err < 0)
+ return err;
+ }
+ goto skip_it;
}
- goto skip_it;
- }
- if (h->nlmsg_type == NLMSG_DONE)
- return 0;
- if (h->nlmsg_type == NLMSG_ERROR) {
- struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
- if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- fprintf(stderr, "ERROR truncated\n");
- } else {
- errno = -err->error;
- perror("RTNETLINK answers");
+ if (h->nlmsg_type == NLMSG_DONE)
+ return 0;
+ if (h->nlmsg_type == NLMSG_ERROR) {
+ struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h);
+ if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+ fprintf(stderr,
+ "ERROR truncated\n");
+ } else {
+ errno = -err->error;
+ perror("RTNETLINK answers");
+ }
+ return -1;
}
- return -1;
- }
- err = filter(&nladdr, h, arg1);
- if (err < 0)
- return err;
+ err = a->filter(&nladdr, h, a->arg1);
+ if (err < 0)
+ return err;
skip_it:
- h = NLMSG_NEXT(h, status);
- }
+ h = NLMSG_NEXT(h, status);
+ }
+ } while (0);
if (msg.msg_flags & MSG_TRUNC) {
fprintf(stderr, "Message truncated\n");
continue;
}
}
+int rtnl_dump_filter(struct rtnl_handle *rth,
+ rtnl_filter_t filter,
+ void *arg1,
+ rtnl_filter_t junk,
+ void *arg2)
+{
+ const struct rtnl_dump_filter_arg a[2] = {
+ { .filter = filter, .arg1 = arg1, .junk = junk, .arg2 = arg2 },
+ { .filter = NULL, .arg1 = NULL, .junk = NULL, .arg2 = NULL }
+ };
+
+ return rtnl_dump_filter_l(rth, a);
+}
+
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer,
unsigned groups, struct nlmsghdr *answer,
rtnl_filter_t junk,