Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion tools/lkl/include/lkl.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ void lkl_register_dbg_handler();
/**
* lkl_add_neighbor - add a permanent arp entry
* @ifindex - the ifindex of the interface
* @af - adress family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
* @ip - ip address of the entry in network byte order
* @mac - mac address of the entry
*/
Expand All @@ -428,6 +428,33 @@ int lkl_add_neighbor(int ifindex, int af, void* addr, void* mac);
*/
int lkl_mount_fs(char *fstype);

/**
* lkl_if_add_ip - add an ip address
* @ifindex - the ifindex of the interface
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
* @addr - ip address of the entry in network byte order
* @netprefix_len - prefix length of the @addr
*/
int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len);

/**
* lkl_if_del_ip - add an ip address
* @ifindex - the ifindex of the interface
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
* @addr - ip address of the entry in network byte order
* @netprefix_len - prefix length of the @addr
*/
int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len);

/**
* lkl_if_wait_ipv6_dad - wait for DAD to be done for a ipv6 address
* must be called after interface is up
*
* @ifindex - the ifindex of the interface
* @addr - ip address of the entry in network byte order
*/
int lkl_if_wait_ipv6_dad(int ifindex, void *addr);

#ifdef __cplusplus
}
#endif
Expand Down
198 changes: 102 additions & 96 deletions tools/lkl/lib/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,41 +87,7 @@ int lkl_if_set_mtu(int ifindex, int mtu)

int lkl_if_set_ipv4(int ifindex, unsigned int addr, unsigned int netmask_len)
{
struct lkl_ifreq ifr;
struct lkl_sockaddr_in *sin;
int err, sock;


sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0);
if (sock < 0)
return sock;

err = ifindex_to_name(sock, &ifr, ifindex);
if (err < 0)
return err;

if (netmask_len >= 31)
return -LKL_EINVAL;

sin = (struct lkl_sockaddr_in *)&ifr.lkl_ifr_addr;
set_sockaddr(sin, addr, 0);

err = lkl_sys_ioctl(sock, LKL_SIOCSIFADDR, (long)&ifr);
if (!err) {
int netmask = (((1<<netmask_len)-1))<<(32-netmask_len);

sin = (struct lkl_sockaddr_in *)&ifr.lkl_ifr_netmask;
set_sockaddr(sin, htonl(netmask), 0);
err = lkl_sys_ioctl(sock, LKL_SIOCSIFNETMASK, (long)&ifr);
if (!err) {
set_sockaddr(sin, htonl(ntohl(addr)|~netmask), 0);
err = lkl_sys_ioctl(sock, LKL_SIOCSIFBRDADDR, (long)&ifr);
}
}

lkl_sys_close(sock);

return err;
return lkl_if_add_ip(ifindex, LKL_AF_INET, &addr, netmask_len);
}

int lkl_set_ipv4_gateway(unsigned int addr)
Expand Down Expand Up @@ -208,7 +174,7 @@ static int parse_rtattr(struct lkl_rtattr *tb[], int max,
rta = LKL_RTA_NEXT(rta, len);
}
if (len)
lkl_printf( "!!!Deficit %d, rta_len=%d\n", len,
lkl_printf("!!!Deficit %d, rta_len=%d\n", len,
rta->rta_len);
return 0;
}
Expand Down Expand Up @@ -244,7 +210,7 @@ static int check_ipv6_dad(struct lkl_sockaddr_nl *nladdr,

len -= LKL_NLMSG_LENGTH(sizeof(*ifa));
if (len < 0) {
lkl_printf( "BUG: wrong nlmsg len %d\n", len);
lkl_printf("BUG: wrong nlmsg len %d\n", len);
return -1;
}

Expand All @@ -267,7 +233,7 @@ static int check_ipv6_dad(struct lkl_sockaddr_nl *nladdr,
return 1;
}
if (ifa_flags & LKL_IFA_F_DADFAILED) {
lkl_printf( "IPV6 DAD failed.\n");
lkl_printf("IPV6 DAD failed.\n");
return -1;
}
if (!(ifa_flags & LKL_IFA_F_TENTATIVE))
Expand Down Expand Up @@ -300,18 +266,18 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,
if (status < 0) {
if (status == -LKL_EINTR || status == -LKL_EAGAIN)
continue;
lkl_printf( "netlink receive error %s (%d)\n",
lkl_printf("netlink receive error %s (%d)\n",
lkl_strerror(status), status);
if (status == -LKL_ENOBUFS)
continue;
return status;
}
if (status == 0) {
lkl_printf( "EOF on netlink\n");
lkl_printf("EOF on netlink\n");
return -1;
}
if (msg.msg_namelen != sizeof(nladdr)) {
lkl_printf( "Sender address length == %d\n",
lkl_printf("Sender address length == %d\n",
msg.msg_namelen);
return -1;
}
Expand All @@ -324,10 +290,10 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,

if (l < 0 || len > status) {
if (msg.msg_flags & LKL_MSG_TRUNC) {
lkl_printf( "Truncated message\n");
lkl_printf("Truncated message\n");
return -1;
}
lkl_printf( "!!!malformed message: len=%d\n",
lkl_printf("!!!malformed message: len=%d\n",
len);
return -1;
}
Expand All @@ -341,17 +307,17 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,
LKL_NLMSG_ALIGN(len));
}
if (msg.msg_flags & LKL_MSG_TRUNC) {
lkl_printf( "Message truncated\n");
lkl_printf("Message truncated\n");
continue;
}
if (status) {
lkl_printf( "!!!Remnant of size %d\n", status);
lkl_printf("!!!Remnant of size %d\n", status);
return -1;
}
}
}

static int wait_ipv6(int ifindex, void *addr)
int lkl_if_wait_ipv6_dad(int ifindex, void *addr)
{
struct addr_filter filter = {.ifindex = ifindex, .addr = addr};
int fd, ret;
Expand Down Expand Up @@ -383,32 +349,15 @@ static int wait_ipv6(int ifindex, void *addr)

int lkl_if_set_ipv6(int ifindex, void *addr, unsigned int netprefix_len)
{
struct lkl_in6_ifreq ifr6;
int err, sock;

if (netprefix_len >= 128)
return -LKL_EINVAL;

sock = lkl_sys_socket(LKL_AF_INET6, LKL_SOCK_DGRAM, 0);
if (sock < 0)
return sock;

memcpy(&ifr6.ifr6_addr.lkl_s6_addr, addr, sizeof(struct lkl_in6_addr));
ifr6.ifr6_ifindex = ifindex;
ifr6.ifr6_prefixlen = netprefix_len;

err = lkl_sys_ioctl(sock, LKL_SIOCSIFADDR, (long)&ifr6);
lkl_sys_close(sock);
int err = lkl_if_add_ip(ifindex, LKL_AF_INET6, addr, netprefix_len);
if (err)
return err;

err = wait_ipv6(ifindex, addr);
return err;
return lkl_if_wait_ipv6_dad(ifindex, addr);
}

/* returns:
* 0 - succeed.
* -1 - error.
* < 0 - error number.
* 1 - should wait for new msg.
*/
static int check_error(struct lkl_sockaddr_nl *nladdr, struct lkl_nlmsghdr *n,
Expand All @@ -427,15 +376,15 @@ static int check_error(struct lkl_sockaddr_nl *nladdr, struct lkl_nlmsghdr *n,
int l = n->nlmsg_len - sizeof(*n);

if (l < (int)sizeof(struct lkl_nlmsgerr))
lkl_printf( "ERROR truncated\n");
lkl_printf("ERROR truncated\n");
else if (!err->error)
return 0;

lkl_printf( "RTNETLINK answers: %s\n",
lkl_printf("RTNETLINK answers: %s\n",
strerror(-err->error));
return -1;
return err->error;
}
lkl_printf( "Unexpected reply!!!\n");
lkl_printf("Unexpected reply!!!\n");
return -1;
}

Expand Down Expand Up @@ -466,60 +415,117 @@ static int rtnl_talk(int fd, struct lkl_nlmsghdr *n)
return status;
}

static int addattr_l(struct lkl_nlmsghdr *n, unsigned int maxlen,
int type, const void *data, int alen)
{
int len = LKL_RTA_LENGTH(alen);
struct lkl_rtattr *rta;

if (LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len) > maxlen) {
lkl_printf("addattr_l ERROR: message exceeded bound of %d\n",
maxlen);
return -1;
}
rta = ((struct lkl_rtattr *) (((void *) (n)) +
LKL_NLMSG_ALIGN(n->nlmsg_len)));
rta->rta_type = type;
rta->rta_len = len;
memcpy(LKL_RTA_DATA(rta), data, alen);
n->nlmsg_len = LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len);
return 0;
}

int lkl_add_neighbor(int ifindex, int af, void* ip, void* mac)
{
struct {
struct lkl_nlmsghdr n;
struct lkl_ndmsg r;
char buf[1024];
} req2;
} req = {
.n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ndmsg)),
.n.nlmsg_type = LKL_RTM_NEWNEIGH,
.n.nlmsg_flags = LKL_NLM_F_REQUEST |
LKL_NLM_F_CREATE | LKL_NLM_F_REPLACE,
.r.ndm_family = af,
.r.ndm_ifindex = ifindex,
.r.ndm_state = LKL_NUD_PERMANENT,

};
int err, addr_sz;
int ndmsglen = LKL_NLMSG_LENGTH(sizeof(struct lkl_ndmsg));
struct lkl_rtattr *dstattr;
int fd;

if (af == LKL_AF_INET)
addr_sz = 4;
else if (af == LKL_AF_INET6)
addr_sz = 16;
else {
lkl_printf( "Bad address family: %d\n", af);
lkl_printf("Bad address family: %d\n", af);
return -1;
}

fd = netlink_sock(0);
if (fd < 0)
return fd;

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

// create the IP attribute
dstattr = (struct lkl_rtattr *)req2.buf;
dstattr->rta_type = LKL_NDA_DST;
dstattr->rta_len = sizeof(struct lkl_rtattr) + addr_sz;
memcpy(((char *)dstattr) + sizeof(struct lkl_rtattr), ip, addr_sz);
ndmsglen += dstattr->rta_len;
addattr_l(&req.n, sizeof(req), LKL_NDA_DST, ip, addr_sz);

// create the MAC attribute
dstattr = (struct lkl_rtattr *)(req2.buf + dstattr->rta_len);
dstattr->rta_type = LKL_NDA_LLADDR;
dstattr->rta_len = sizeof(struct lkl_rtattr) + 6;
memcpy(((char *)dstattr) + sizeof(struct lkl_rtattr), mac, 6);
ndmsglen += dstattr->rta_len;
addattr_l(&req.n, sizeof(req), LKL_NDA_LLADDR, mac, 6);

err = rtnl_talk(fd, &req.n);
lkl_sys_close(fd);
return err;
}

static int ipaddr_modify(int cmd, int flags, int ifindex, int af, void *addr,
unsigned int netprefix_len)
{
struct {
struct lkl_nlmsghdr n;
struct lkl_ifaddrmsg ifa;
char buf[256];
} req = {
.n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ifaddrmsg)),
.n.nlmsg_flags = LKL_NLM_F_REQUEST | flags,
.n.nlmsg_type = cmd,
.ifa.ifa_family = af,
.ifa.ifa_prefixlen = netprefix_len,
.ifa.ifa_index = ifindex,
};
int err, addr_sz;
int fd;

// fill in the netlink message header
req2.n.nlmsg_len = ndmsglen;
req2.n.nlmsg_type = LKL_RTM_NEWNEIGH;
req2.n.nlmsg_flags =
LKL_NLM_F_REQUEST | LKL_NLM_F_CREATE | LKL_NLM_F_REPLACE;
if (af == LKL_AF_INET)
addr_sz = 4;
else if (af == LKL_AF_INET6)
addr_sz = 16;
else {
lkl_printf("Bad address family: %d\n", af);
return -1;
}

fd = netlink_sock(0);
if (fd < 0)
return fd;

// fill in the netlink message NEWNEIGH
req2.r.ndm_family = af;
req2.r.ndm_ifindex = ifindex;
req2.r.ndm_state = LKL_NUD_PERMANENT;
// create the IP attribute
addattr_l(&req.n, sizeof(req), LKL_IFA_LOCAL, addr, addr_sz);

err = rtnl_talk(fd, &req2.n);
err = rtnl_talk(fd, &req.n);

lkl_sys_close(fd);
return err;
}

int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len)
{
return ipaddr_modify(LKL_RTM_NEWADDR, LKL_NLM_F_CREATE | LKL_NLM_F_EXCL,
ifindex, af, addr, netprefix_len);
}

int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len)
{
return ipaddr_modify(LKL_RTM_DELADDR, 0, ifindex, af,
addr, netprefix_len);
}