Skip to content

Commit 8f15f09

Browse files
authored
Merge pull request torvalds#254 from liuyuan10/multiip
lkL-tools: add API to add/del ip addresses
2 parents 4b77c32 + 44c9b9b commit 8f15f09

File tree

2 files changed

+130
-97
lines changed

2 files changed

+130
-97
lines changed

tools/lkl/include/lkl.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ void lkl_register_dbg_handler();
415415
/**
416416
* lkl_add_neighbor - add a permanent arp entry
417417
* @ifindex - the ifindex of the interface
418-
* @af - adress family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
418+
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
419419
* @ip - ip address of the entry in network byte order
420420
* @mac - mac address of the entry
421421
*/
@@ -428,6 +428,33 @@ int lkl_add_neighbor(int ifindex, int af, void* addr, void* mac);
428428
*/
429429
int lkl_mount_fs(char *fstype);
430430

431+
/**
432+
* lkl_if_add_ip - add an ip address
433+
* @ifindex - the ifindex of the interface
434+
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
435+
* @addr - ip address of the entry in network byte order
436+
* @netprefix_len - prefix length of the @addr
437+
*/
438+
int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len);
439+
440+
/**
441+
* lkl_if_del_ip - add an ip address
442+
* @ifindex - the ifindex of the interface
443+
* @af - address family of the ip address. Must be LKL_AF_INET or LKL_AF_INET6
444+
* @addr - ip address of the entry in network byte order
445+
* @netprefix_len - prefix length of the @addr
446+
*/
447+
int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len);
448+
449+
/**
450+
* lkl_if_wait_ipv6_dad - wait for DAD to be done for a ipv6 address
451+
* must be called after interface is up
452+
*
453+
* @ifindex - the ifindex of the interface
454+
* @addr - ip address of the entry in network byte order
455+
*/
456+
int lkl_if_wait_ipv6_dad(int ifindex, void *addr);
457+
431458
#ifdef __cplusplus
432459
}
433460
#endif

tools/lkl/lib/net.c

Lines changed: 102 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -87,41 +87,7 @@ int lkl_if_set_mtu(int ifindex, int mtu)
8787

8888
int lkl_if_set_ipv4(int ifindex, unsigned int addr, unsigned int netmask_len)
8989
{
90-
struct lkl_ifreq ifr;
91-
struct lkl_sockaddr_in *sin;
92-
int err, sock;
93-
94-
95-
sock = lkl_sys_socket(LKL_AF_INET, LKL_SOCK_DGRAM, 0);
96-
if (sock < 0)
97-
return sock;
98-
99-
err = ifindex_to_name(sock, &ifr, ifindex);
100-
if (err < 0)
101-
return err;
102-
103-
if (netmask_len >= 31)
104-
return -LKL_EINVAL;
105-
106-
sin = (struct lkl_sockaddr_in *)&ifr.lkl_ifr_addr;
107-
set_sockaddr(sin, addr, 0);
108-
109-
err = lkl_sys_ioctl(sock, LKL_SIOCSIFADDR, (long)&ifr);
110-
if (!err) {
111-
int netmask = (((1<<netmask_len)-1))<<(32-netmask_len);
112-
113-
sin = (struct lkl_sockaddr_in *)&ifr.lkl_ifr_netmask;
114-
set_sockaddr(sin, htonl(netmask), 0);
115-
err = lkl_sys_ioctl(sock, LKL_SIOCSIFNETMASK, (long)&ifr);
116-
if (!err) {
117-
set_sockaddr(sin, htonl(ntohl(addr)|~netmask), 0);
118-
err = lkl_sys_ioctl(sock, LKL_SIOCSIFBRDADDR, (long)&ifr);
119-
}
120-
}
121-
122-
lkl_sys_close(sock);
123-
124-
return err;
90+
return lkl_if_add_ip(ifindex, LKL_AF_INET, &addr, netmask_len);
12591
}
12692

12793
int lkl_set_ipv4_gateway(unsigned int addr)
@@ -208,7 +174,7 @@ static int parse_rtattr(struct lkl_rtattr *tb[], int max,
208174
rta = LKL_RTA_NEXT(rta, len);
209175
}
210176
if (len)
211-
lkl_printf( "!!!Deficit %d, rta_len=%d\n", len,
177+
lkl_printf("!!!Deficit %d, rta_len=%d\n", len,
212178
rta->rta_len);
213179
return 0;
214180
}
@@ -244,7 +210,7 @@ static int check_ipv6_dad(struct lkl_sockaddr_nl *nladdr,
244210

245211
len -= LKL_NLMSG_LENGTH(sizeof(*ifa));
246212
if (len < 0) {
247-
lkl_printf( "BUG: wrong nlmsg len %d\n", len);
213+
lkl_printf("BUG: wrong nlmsg len %d\n", len);
248214
return -1;
249215
}
250216

@@ -267,7 +233,7 @@ static int check_ipv6_dad(struct lkl_sockaddr_nl *nladdr,
267233
return 1;
268234
}
269235
if (ifa_flags & LKL_IFA_F_DADFAILED) {
270-
lkl_printf( "IPV6 DAD failed.\n");
236+
lkl_printf("IPV6 DAD failed.\n");
271237
return -1;
272238
}
273239
if (!(ifa_flags & LKL_IFA_F_TENTATIVE))
@@ -300,18 +266,18 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,
300266
if (status < 0) {
301267
if (status == -LKL_EINTR || status == -LKL_EAGAIN)
302268
continue;
303-
lkl_printf( "netlink receive error %s (%d)\n",
269+
lkl_printf("netlink receive error %s (%d)\n",
304270
lkl_strerror(status), status);
305271
if (status == -LKL_ENOBUFS)
306272
continue;
307273
return status;
308274
}
309275
if (status == 0) {
310-
lkl_printf( "EOF on netlink\n");
276+
lkl_printf("EOF on netlink\n");
311277
return -1;
312278
}
313279
if (msg.msg_namelen != sizeof(nladdr)) {
314-
lkl_printf( "Sender address length == %d\n",
280+
lkl_printf("Sender address length == %d\n",
315281
msg.msg_namelen);
316282
return -1;
317283
}
@@ -324,10 +290,10 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,
324290

325291
if (l < 0 || len > status) {
326292
if (msg.msg_flags & LKL_MSG_TRUNC) {
327-
lkl_printf( "Truncated message\n");
293+
lkl_printf("Truncated message\n");
328294
return -1;
329295
}
330-
lkl_printf( "!!!malformed message: len=%d\n",
296+
lkl_printf("!!!malformed message: len=%d\n",
331297
len);
332298
return -1;
333299
}
@@ -341,17 +307,17 @@ static int rtnl_listen(int fd, int (*handler)(struct lkl_sockaddr_nl *nladdr,
341307
LKL_NLMSG_ALIGN(len));
342308
}
343309
if (msg.msg_flags & LKL_MSG_TRUNC) {
344-
lkl_printf( "Message truncated\n");
310+
lkl_printf("Message truncated\n");
345311
continue;
346312
}
347313
if (status) {
348-
lkl_printf( "!!!Remnant of size %d\n", status);
314+
lkl_printf("!!!Remnant of size %d\n", status);
349315
return -1;
350316
}
351317
}
352318
}
353319

354-
static int wait_ipv6(int ifindex, void *addr)
320+
int lkl_if_wait_ipv6_dad(int ifindex, void *addr)
355321
{
356322
struct addr_filter filter = {.ifindex = ifindex, .addr = addr};
357323
int fd, ret;
@@ -383,32 +349,15 @@ static int wait_ipv6(int ifindex, void *addr)
383349

384350
int lkl_if_set_ipv6(int ifindex, void *addr, unsigned int netprefix_len)
385351
{
386-
struct lkl_in6_ifreq ifr6;
387-
int err, sock;
388-
389-
if (netprefix_len >= 128)
390-
return -LKL_EINVAL;
391-
392-
sock = lkl_sys_socket(LKL_AF_INET6, LKL_SOCK_DGRAM, 0);
393-
if (sock < 0)
394-
return sock;
395-
396-
memcpy(&ifr6.ifr6_addr.lkl_s6_addr, addr, sizeof(struct lkl_in6_addr));
397-
ifr6.ifr6_ifindex = ifindex;
398-
ifr6.ifr6_prefixlen = netprefix_len;
399-
400-
err = lkl_sys_ioctl(sock, LKL_SIOCSIFADDR, (long)&ifr6);
401-
lkl_sys_close(sock);
352+
int err = lkl_if_add_ip(ifindex, LKL_AF_INET6, addr, netprefix_len);
402353
if (err)
403354
return err;
404-
405-
err = wait_ipv6(ifindex, addr);
406-
return err;
355+
return lkl_if_wait_ipv6_dad(ifindex, addr);
407356
}
408357

409358
/* returns:
410359
* 0 - succeed.
411-
* -1 - error.
360+
* < 0 - error number.
412361
* 1 - should wait for new msg.
413362
*/
414363
static int check_error(struct lkl_sockaddr_nl *nladdr, struct lkl_nlmsghdr *n,
@@ -427,15 +376,15 @@ static int check_error(struct lkl_sockaddr_nl *nladdr, struct lkl_nlmsghdr *n,
427376
int l = n->nlmsg_len - sizeof(*n);
428377

429378
if (l < (int)sizeof(struct lkl_nlmsgerr))
430-
lkl_printf( "ERROR truncated\n");
379+
lkl_printf("ERROR truncated\n");
431380
else if (!err->error)
432381
return 0;
433382

434-
lkl_printf( "RTNETLINK answers: %s\n",
383+
lkl_printf("RTNETLINK answers: %s\n",
435384
strerror(-err->error));
436-
return -1;
385+
return err->error;
437386
}
438-
lkl_printf( "Unexpected reply!!!\n");
387+
lkl_printf("Unexpected reply!!!\n");
439388
return -1;
440389
}
441390

@@ -466,60 +415,117 @@ static int rtnl_talk(int fd, struct lkl_nlmsghdr *n)
466415
return status;
467416
}
468417

418+
static int addattr_l(struct lkl_nlmsghdr *n, unsigned int maxlen,
419+
int type, const void *data, int alen)
420+
{
421+
int len = LKL_RTA_LENGTH(alen);
422+
struct lkl_rtattr *rta;
423+
424+
if (LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len) > maxlen) {
425+
lkl_printf("addattr_l ERROR: message exceeded bound of %d\n",
426+
maxlen);
427+
return -1;
428+
}
429+
rta = ((struct lkl_rtattr *) (((void *) (n)) +
430+
LKL_NLMSG_ALIGN(n->nlmsg_len)));
431+
rta->rta_type = type;
432+
rta->rta_len = len;
433+
memcpy(LKL_RTA_DATA(rta), data, alen);
434+
n->nlmsg_len = LKL_NLMSG_ALIGN(n->nlmsg_len) + LKL_RTA_ALIGN(len);
435+
return 0;
436+
}
437+
469438
int lkl_add_neighbor(int ifindex, int af, void* ip, void* mac)
470439
{
471440
struct {
472441
struct lkl_nlmsghdr n;
473442
struct lkl_ndmsg r;
474443
char buf[1024];
475-
} req2;
444+
} req = {
445+
.n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ndmsg)),
446+
.n.nlmsg_type = LKL_RTM_NEWNEIGH,
447+
.n.nlmsg_flags = LKL_NLM_F_REQUEST |
448+
LKL_NLM_F_CREATE | LKL_NLM_F_REPLACE,
449+
.r.ndm_family = af,
450+
.r.ndm_ifindex = ifindex,
451+
.r.ndm_state = LKL_NUD_PERMANENT,
452+
453+
};
476454
int err, addr_sz;
477-
int ndmsglen = LKL_NLMSG_LENGTH(sizeof(struct lkl_ndmsg));
478-
struct lkl_rtattr *dstattr;
479455
int fd;
480456

481457
if (af == LKL_AF_INET)
482458
addr_sz = 4;
483459
else if (af == LKL_AF_INET6)
484460
addr_sz = 16;
485461
else {
486-
lkl_printf( "Bad address family: %d\n", af);
462+
lkl_printf("Bad address family: %d\n", af);
487463
return -1;
488464
}
489465

490466
fd = netlink_sock(0);
491467
if (fd < 0)
492468
return fd;
493469

494-
memset(&req2, 0, sizeof(req2));
495-
496470
// create the IP attribute
497-
dstattr = (struct lkl_rtattr *)req2.buf;
498-
dstattr->rta_type = LKL_NDA_DST;
499-
dstattr->rta_len = sizeof(struct lkl_rtattr) + addr_sz;
500-
memcpy(((char *)dstattr) + sizeof(struct lkl_rtattr), ip, addr_sz);
501-
ndmsglen += dstattr->rta_len;
471+
addattr_l(&req.n, sizeof(req), LKL_NDA_DST, ip, addr_sz);
502472

503473
// create the MAC attribute
504-
dstattr = (struct lkl_rtattr *)(req2.buf + dstattr->rta_len);
505-
dstattr->rta_type = LKL_NDA_LLADDR;
506-
dstattr->rta_len = sizeof(struct lkl_rtattr) + 6;
507-
memcpy(((char *)dstattr) + sizeof(struct lkl_rtattr), mac, 6);
508-
ndmsglen += dstattr->rta_len;
474+
addattr_l(&req.n, sizeof(req), LKL_NDA_LLADDR, mac, 6);
475+
476+
err = rtnl_talk(fd, &req.n);
477+
lkl_sys_close(fd);
478+
return err;
479+
}
480+
481+
static int ipaddr_modify(int cmd, int flags, int ifindex, int af, void *addr,
482+
unsigned int netprefix_len)
483+
{
484+
struct {
485+
struct lkl_nlmsghdr n;
486+
struct lkl_ifaddrmsg ifa;
487+
char buf[256];
488+
} req = {
489+
.n.nlmsg_len = LKL_NLMSG_LENGTH(sizeof(struct lkl_ifaddrmsg)),
490+
.n.nlmsg_flags = LKL_NLM_F_REQUEST | flags,
491+
.n.nlmsg_type = cmd,
492+
.ifa.ifa_family = af,
493+
.ifa.ifa_prefixlen = netprefix_len,
494+
.ifa.ifa_index = ifindex,
495+
};
496+
int err, addr_sz;
497+
int fd;
509498

510-
// fill in the netlink message header
511-
req2.n.nlmsg_len = ndmsglen;
512-
req2.n.nlmsg_type = LKL_RTM_NEWNEIGH;
513-
req2.n.nlmsg_flags =
514-
LKL_NLM_F_REQUEST | LKL_NLM_F_CREATE | LKL_NLM_F_REPLACE;
499+
if (af == LKL_AF_INET)
500+
addr_sz = 4;
501+
else if (af == LKL_AF_INET6)
502+
addr_sz = 16;
503+
else {
504+
lkl_printf("Bad address family: %d\n", af);
505+
return -1;
506+
}
507+
508+
fd = netlink_sock(0);
509+
if (fd < 0)
510+
return fd;
515511

516-
// fill in the netlink message NEWNEIGH
517-
req2.r.ndm_family = af;
518-
req2.r.ndm_ifindex = ifindex;
519-
req2.r.ndm_state = LKL_NUD_PERMANENT;
512+
// create the IP attribute
513+
addattr_l(&req.n, sizeof(req), LKL_IFA_LOCAL, addr, addr_sz);
520514

521-
err = rtnl_talk(fd, &req2.n);
515+
err = rtnl_talk(fd, &req.n);
522516

523517
lkl_sys_close(fd);
524518
return err;
525519
}
520+
521+
int lkl_if_add_ip(int ifindex, int af, void *addr, unsigned int netprefix_len)
522+
{
523+
return ipaddr_modify(LKL_RTM_NEWADDR, LKL_NLM_F_CREATE | LKL_NLM_F_EXCL,
524+
ifindex, af, addr, netprefix_len);
525+
}
526+
527+
int lkl_if_del_ip(int ifindex, int af, void *addr, unsigned int netprefix_len)
528+
{
529+
return ipaddr_modify(LKL_RTM_DELADDR, 0, ifindex, af,
530+
addr, netprefix_len);
531+
}

0 commit comments

Comments
 (0)