Questions on Netlink sockets
Bhaskar Upadhyayula
bu.kernel at gmail.com
Wed Aug 19 03:07:08 EDT 2015
Hi Rami,
Thanks for the response. With the help of a colleague, I was able to
debug the issue. I was not *nesting* the attributes and not adjusting
the attribute lengths properly. I am still figuring out how nesting
works exactly and the need for it.
If anyone is interested, attaching the working code (inline as well,
if attachment is not permitted on kernelnewbies).
Thanks.
PS: I am humbled to see a reply from you. I read Chapter 2 from your
book to understand netlink sockets.
=======
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#define MAX_PAYLOAD 2048
/* All globals initialized to 0 */
struct sockaddr_nl src, dst;
struct iovec iov;
struct msghdr msg;
int sock_fd;
struct {
struct nlmsghdr n;
struct ifinfomsg i;
char buf[MAX_PAYLOAD];
} req;
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
/* Function from libnetlink.h */
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
int alen)
{
int len = RTA_LENGTH(alen);
struct rtattr *rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr, "addattr_l ERROR: message exceeded bound of
%d\n",maxlen);
return -1;
}
rta = NLMSG_TAIL(n);
rta->rta_type = type;
rta->rta_len = len;
memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0;
}
void usage()
{
fprintf(stderr, "Incorrect usage\n");
fprintf(stderr, "./nl <vlan_intf_name> <intf_name> <vlan_id>\n");
}
void dumpData(const char *note, const char *msg, unsigned int len)
{
// no error checks
unsigned int i;
//fprintf(stderr, "\n%s(%u):\n", note, len);
for(i=0; i<len; ++i) {
fprintf(stderr, "%02X ",msg[i]);
if (i>0 && i%15 == 0)
fprintf(stderr, "\n");
}
fprintf(stderr,"\n");
}
void main(int argc, char *argv[])
{
char *type, *intf_name, *vlan_intf_name;
__u16 vlan_id;
int ifindex;
if (argc != 4) {
usage();
return;
}
vlan_intf_name = argv[1];
intf_name = argv[2];
vlan_id = atoi(argv[3]);
fprintf(stderr, "%s, %s, %d\n", vlan_intf_name, intf_name, vlan_id);
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock_fd < 0)
return;
memset(&src, 0, sizeof(src));
memset(&dst, 0, sizeof(dst));
memset(&req, 0, sizeof(req));
/* Details of source end of socket */
src.nl_family = AF_NETLINK;
src.nl_pid = getpid();
bind(sock_fd, (struct sockaddr *)&src, sizeof(src));
/* Details of destination side of socket */
dst.nl_family = AF_NETLINK;
req.n.nlmsg_len = NLMSG_SPACE(sizeof(struct ifinfomsg));
req.n.nlmsg_pid = getpid();
req.n.nlmsg_type = RTM_NEWLINK;
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE ;//| NLM_F_EXCL;
ifindex = if_nametoindex(intf_name);
req.i.ifi_family = AF_UNSPEC;
//req.i.ifi_index = ifindex;
struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vlan", 4);
struct rtattr * data = NLMSG_TAIL(&req.n);
addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
addattr_l(&req.n, sizeof(req), IFLA_VLAN_ID, &vlan_id, 2);
data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
addattr_l(&req.n, sizeof(req), IFLA_LINK, &ifindex, 4);
addattr_l(&req.n, sizeof(req), IFLA_IFNAME, vlan_intf_name,
strlen(vlan_intf_name)+1);
/* send msg to kernel */
if( send(sock_fd, &req, req.n.nlmsg_len, 0) < 0)
fprintf(stderr, "failed write\n");
//dumpData("Dst socket", (char *)msg.msg_name, msg.msg_namelen);
dumpData("Netlink msg", (char *)&req.n, req.n.nlmsg_len);
close(sock_fd);
}
=======
On Mon, Aug 17, 2015 at 9:18 PM, Rami Rosen <roszenrami at gmail.com> wrote:
> Hi, Bhaskar,
>
> Indeed the netdev mailing list is too advanced for this.
>
> Do you get any error as a result of sending this netlink message ?
> (I mean error in userspace or in kernel; if there is an error message
> in the kernel it can be viewed by looking at the end of dmesg output)
>
> Further more, I suggest that you will post the code here. The concept
> itself is right, It should work, you either build the netlink message
> incorrectly or send it incorrectly, so it seems.
>
> Regards,
> Rami Rosen
> http://ramirose.wix.com/ramirosen
>
>
> On 18 August 2015 at 01:55, Bhaskar Upadhyayula <bu.kernel at gmail.com> wrote:
>> Hello,
>>
>> I want to check with the group if this is right mailing list to post
>> my question.
>>
>> Here is what I am doing.
>>
>> + From a user-space program, mimicking the behavior of creating a VLAN
>> interface when we execute the following ip command:
>> $ ip link add name <vlan-intf-name> link <parent-intf-name> type
>> vlan id <id>
>>
>> Example: $ ip link add name dummy.110 link dummy type vlan id 110
>>
>> + My program open's a netlink socket and sends information to kernel
>> (interface names, vlan tags etc). My code more or less follows the
>> code in iproute2/ip/iplink.c
>>
>> + My code is not creating VLAN interface as executed by the 'ip link
>> ...' command.
>>
>> I have a few questions around this and can post my code, if required.
>>
>> But please let me know if this is right mailing list or should I post
>> on netdev list (which I feel is for advanced network questions).
>>
>> Thx.
>>
>> _______________________________________________
>> Kernelnewbies mailing list
>> Kernelnewbies at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
-------------- next part --------------
A non-text attachment was scrubbed...
Name: vlan_nl.c
Type: text/x-csrc
Size: 3594 bytes
Desc: not available
Url : http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20150819/0f5717fb/attachment-0001.bin
More information about the Kernelnewbies
mailing list