mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 09:49:05 +00:00
Factor out a add_rtattr_addr function to add a source or destination spec.
This is used to restrict what routes the Netlink layer will return to us.
This commit is contained in:
@@ -2990,6 +2990,66 @@ static int set_sockaddr(struct sockaddr_storage *ss, int af, void *data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add rtattrs to a netlink message specifying a source or destination address.
|
||||||
|
rta_type must be RTA_SRC or RTA_DST. This function adds either 1 or 2
|
||||||
|
rtattrs: it always adds either an RTA_SRC or RTA_DST, depending on rta_type.
|
||||||
|
It also adds either RTA_IIF or RTA_OIF if the address family is AF_INET6 and
|
||||||
|
the sockaddr_in6 has a non-zero sin6_scope_id. */
|
||||||
|
static void add_rtattr_addr(struct nlmsghdr *nlmsg,
|
||||||
|
struct rtattr **rtattr, unsigned int *len,
|
||||||
|
unsigned char rta_type,
|
||||||
|
const struct sockaddr_storage *ss) {
|
||||||
|
struct rtmsg *rtmsg;
|
||||||
|
const void *addr;
|
||||||
|
size_t addrlen;
|
||||||
|
int ifindex;
|
||||||
|
|
||||||
|
assert(rta_type == RTA_SRC || rta_type == RTA_DST);
|
||||||
|
|
||||||
|
ifindex = 0;
|
||||||
|
|
||||||
|
if (ss->ss_family == AF_INET) {
|
||||||
|
addr = &((struct sockaddr_in *) ss)->sin_addr.s_addr;
|
||||||
|
addrlen = IP_ADDR_LEN;
|
||||||
|
} else if (ss->ss_family == AF_INET6) {
|
||||||
|
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
|
||||||
|
|
||||||
|
addr = sin6->sin6_addr.s6_addr;
|
||||||
|
addrlen = IP6_ADDR_LEN;
|
||||||
|
ifindex = sin6->sin6_scope_id;
|
||||||
|
} else {
|
||||||
|
netutil_fatal("%s: unknown address family %d", __func__, ss->ss_family);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtmsg = (struct rtmsg *) (nlmsg + 1);
|
||||||
|
if (rta_type == RTA_SRC)
|
||||||
|
rtmsg->rtm_src_len = addrlen * 8;
|
||||||
|
else
|
||||||
|
rtmsg->rtm_dst_len = addrlen * 8;
|
||||||
|
|
||||||
|
/* Add an rtattr for the address. */
|
||||||
|
(*rtattr)->rta_type = rta_type;
|
||||||
|
(*rtattr)->rta_len = RTA_LENGTH(addrlen);
|
||||||
|
assert(RTA_OK(*rtattr, *len));
|
||||||
|
memcpy(RTA_DATA(*rtattr), addr, addrlen);
|
||||||
|
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + (*rtattr)->rta_len;
|
||||||
|
*rtattr = RTA_NEXT(*rtattr, len);
|
||||||
|
|
||||||
|
/* Specific interface (sin6_scope_id) requested? */
|
||||||
|
if (ifindex > 0) {
|
||||||
|
/* Add an rtattr for the interface. */
|
||||||
|
if (rta_type == RTA_SRC)
|
||||||
|
(*rtattr)->rta_type = RTA_IIF;
|
||||||
|
else
|
||||||
|
(*rtattr)->rta_type = RTA_OIF;
|
||||||
|
(*rtattr)->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
||||||
|
assert(RTA_OK(*rtattr, *len));
|
||||||
|
*(uint32_t *) RTA_DATA(*rtattr) = ifindex;
|
||||||
|
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + (*rtattr)->rta_len;
|
||||||
|
*rtattr = RTA_NEXT(*rtattr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Does route_dst using the Linux-specific rtnetlink interface. See rtnetlink(3)
|
/* Does route_dst using the Linux-specific rtnetlink interface. See rtnetlink(3)
|
||||||
and rtnetlink(7). */
|
and rtnetlink(7). */
|
||||||
static int route_dst_netlink(const struct sockaddr_storage *dst,
|
static int route_dst_netlink(const struct sockaddr_storage *dst,
|
||||||
@@ -3002,25 +3062,8 @@ static int route_dst_netlink(const struct sockaddr_storage *dst,
|
|||||||
struct rtmsg *rtmsg;
|
struct rtmsg *rtmsg;
|
||||||
struct rtattr *rtattr;
|
struct rtattr *rtattr;
|
||||||
unsigned char buf[512];
|
unsigned char buf[512];
|
||||||
const void *addr;
|
unsigned int len;
|
||||||
size_t addrlen;
|
int fd, rc;
|
||||||
int ifindex;
|
|
||||||
int fd, rc, len;
|
|
||||||
|
|
||||||
ifindex = 0;
|
|
||||||
|
|
||||||
if (dst->ss_family == AF_INET) {
|
|
||||||
addr = &((struct sockaddr_in *) dst)->sin_addr.s_addr;
|
|
||||||
addrlen = IP_ADDR_LEN;
|
|
||||||
} else if (dst->ss_family == AF_INET6) {
|
|
||||||
const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) dst;
|
|
||||||
|
|
||||||
addr = sin6->sin6_addr.s6_addr;
|
|
||||||
addrlen = IP6_ADDR_LEN;
|
|
||||||
ifindex = sin6->sin6_scope_id;
|
|
||||||
} else {
|
|
||||||
netutil_fatal("%s: unknown address family %d", __func__, dst->ss_family);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
@@ -3044,28 +3087,12 @@ static int route_dst_netlink(const struct sockaddr_storage *dst,
|
|||||||
|
|
||||||
rtmsg = (struct rtmsg *) (nlmsg + 1);
|
rtmsg = (struct rtmsg *) (nlmsg + 1);
|
||||||
rtmsg->rtm_family = dst->ss_family;
|
rtmsg->rtm_family = dst->ss_family;
|
||||||
rtmsg->rtm_dst_len = addrlen * 8;
|
|
||||||
|
|
||||||
rtattr = RTM_RTA(rtmsg);
|
rtattr = RTM_RTA(rtmsg);
|
||||||
len = sizeof(buf) - ((unsigned char *) rtattr - buf);
|
len = sizeof(buf) - ((unsigned char *) RTM_RTA(rtmsg) - buf);
|
||||||
|
|
||||||
/* Add an rtattr for destination address. */
|
/* Add rtattrs for destination address and interface. */
|
||||||
rtattr->rta_type = RTA_DST;
|
add_rtattr_addr(nlmsg, &rtattr, &len, RTA_DST, dst);
|
||||||
rtattr->rta_len = RTA_LENGTH(addrlen);
|
|
||||||
assert(RTA_OK(rtattr, len));
|
|
||||||
memcpy(RTA_DATA(rtattr), addr, addrlen);
|
|
||||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + rtattr->rta_len;
|
|
||||||
|
|
||||||
/* Specific interface (sin6_scope_id) requested? */
|
|
||||||
if (ifindex > 0) {
|
|
||||||
/* Add an rtattr for outgoing interface. */
|
|
||||||
rtattr = RTA_NEXT(rtattr, len);
|
|
||||||
rtattr->rta_type = RTA_OIF;
|
|
||||||
rtattr->rta_len = RTA_LENGTH(sizeof(uint32_t));
|
|
||||||
assert(RTA_OK(rtattr, len));
|
|
||||||
*(uint32_t *) RTA_DATA(rtattr) = ifindex;
|
|
||||||
nlmsg->nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsg_len) + rtattr->rta_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
iov.iov_base = nlmsg;
|
iov.iov_base = nlmsg;
|
||||||
iov.iov_len = nlmsg->nlmsg_len;
|
iov.iov_len = nlmsg->nlmsg_len;
|
||||||
|
|||||||
Reference in New Issue
Block a user