For socket creation, take a look at the code of sys_socketcall()
asmlinkage int sys_socketcall(int call, unsigned long *args)
{
.
case SYS_SOCKET:
err = sys_socket(a0,a1,a[2]);
break;
.
}
In sys_socket in net/socket.c the socket is created and a socket descriptor assigned for future reference. The section of the code is
asmlinkage int sys_socket(int family, int type, int protocol)
{
.
retval = sock_create(family, type, protocol, &sock);
.
retval = get_fd(sock->inode);
.
}
The sections of code relevant in sock_create are
int sock_create(int family, int type, int protocol, struct socket **res)
{
.
.
sock = sock_alloc();
i = net_families[family]->create(sock, protocol);
.
.
}
For netlink sockets, as described earlier, netlink_create is called. This function associates the operations of the protocol with the socket.
static int netlink_create(struct socket *sock, int protocol)
{
.
.
sock->ops = &netlink_ops;
.
.
}
netlink_ops gives the list of function pointers for the various operation associated with the netlink sockets.
struct proto_ops netlink_ops = {
PF_NETLINK,
sock_no_dup,
netlink_release,
netlink_bind,
netlink_connect,
sock_no_socketpair,
sock_no_accept,
netlink_getname,
datagram_poll,
sock_no_ioctl,
sock_no_listen,
sock_no_shutdown,
sock_no_setsockopt,
sock_no_getsockopt,
sock_no_fcntl,
netlink_sendmsg,
netlink_recvmsg
};
After the netlink socket is created, the next step is to bind the socket, when a bind is issued from the user level, the sys_bind finction is called in the kernel, this in turn calls the bind function corresponding to the socket created, in our case it will be the netlink_bind that is called.
In netlink_bind, netlink_insert() is called which creates an entry for this netlink socket in the nl_table which is a list of sock structures.
static void netlink_insert(struct sock *sk)
{
sk->next = nl_table[sk->protocol];
nl_table[sk->protocol] = sk;
}
So the user code for the creation and binding of the netlink socket can be
summarised as
struct sockaddr_nl address; sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); bind(sock_fd, (struct sockaddr*)&address, sizeof(address));
where sockaddr_nl is defined in include/linux/netlink.h
struct sockaddr_nl
{
sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
__u32 nl_pid; /* process pid */
__u32 nl_groups; /* multicast groups mask */
};
the family is AF_NETLINK, nl_groups is used for multicast options and the nl_pid is used to represent the process id, if this given as zero, the kernel gets the current->pid from the task structure and fills it. In the kernel the check for the pid is done and if is zero, netlink_autobind() is called which does the following,
static int netlink_autobind(struct socket *sock)
{
struct sock *sk = sock->sk;
struct sock *osk;
sk->protinfo.af_netlink.groups = 0;
sk->protinfo.af_netlink.pid = current->pid;
.
.
netlink_insert(sk);
}