Netlink Sockets Tour

Last updated 2002-01-31 10:42 am

Cast a spell on the socket!

sock_fd = socket( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
First of all, open a NETLINK socket with socket().
Argument Value Description
  1st: Address family AF_NETLINK Address family is NETLINK
  2nd: Socket type SOCK_RAW Raw network protocol access
  3rd: Netlink family NETLINK_ROUTE

Modify most of IPv4 control parameters


Receive packets sent by IPv4 firewall


Manage ARP table from user space


IPv6 routing table update


Currently not implemented


Ethertap device


Reserved for ENskip

Welcome to the dungeon of Linux networking code!


  Final setup functions are called from do_baseic_setup() in init/main.c.
  sock_init() is also called in this function.

  do_basic_setup() manages interesting jobs including initial RAM disk (initrd), and so on.


static void __init do_basic_setup(void) { ... /* * Ok, at this point all CPU's should be initialized, so * we can start looking into devices.. */ ... /* Networking initialization needs a process context */ sock_init(); ...


  At the beginning of function, you can see a familiar message.
 Initialize address families. NPROTO is currently defined as 32.
include/linux/net.h:#define NPROTO 32 /* should be enough for now.. */


void __init sock_init(void) { int i; printk(KERN_INFO "Linux NET4.0 for Linux 2.2\n"); printk(KERN_INFO "Based upon Swansea University Computer Society NET3.039\n"); /* * Initialize all address (protocol) families. */ for (i = 0; i < NPROTO; i++) net_families[i] = NULL; /* * Initialize sock SLAB cache. */ sk_init(); /* * Attach the firewall module if configured */ #ifdef CONFIG_FIREWALL fwchain_init(); #endif /* * Initialize the protocols module. */ proto_init(); /* * The netlink device handler may be needed early. */ #ifdef CONFIG_RTNETLINK rtnetlink_init(); #endif #ifdef CONFIG_NETLINK_DEV init_netlink(); #endif }


  Network protocol table is stored in a global array, protocols[], which is defined in net/protocols.c.
 All of built in protocols will be kicked out.
  In short, net_families[ PF_NETLINK ] = &netlink_family_ops will be executed.


void __init proto_init(void) { extern struct net_proto protocols[]; /* Network protocols */ struct net_proto *pro; /* Kick all configured protocols. */ pro = protocols; while (pro->name != NULL) { (*pro->init_func)(pro); pro++; } /* We're all done... */ }


/* * Protocol Table */ struct net_proto protocols[] = { #ifdef CONFIG_NETLINK { "NETLINK", netlink_proto_init }, #endif #ifdef CONFIG_PACKET { "PACKET", packet_proto_init }, #endif #ifdef CONFIG_UNIX { "UNIX", unix_proto_init }, /* Unix domain socket family */ #endif ... #ifdef CONFIG_INET { "INET", inet_proto_init }, /* TCP/IP */ #ifdef CONFIG_IPV6 { "INET6", inet6_proto_init}, /* IPv6 */ #endif #endif ... { NULL, NULL } /* End marker */ };


static int netlink_create(struct socket *sock, int protocol) { struct sock *sk; sock->state = SS_UNCONNECTED; if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) return -ESOCKTNOSUPPORT; if (protocol<0 || protocol >= MAX_LINKS) return -EPROTONOSUPPORT; sock->ops = &netlink_ops; sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1); if (!sk) return -ENOMEM; sock_init_data(sock,sk); sk->destruct = NULL; sk->protocol=protocol; return 0; } ... 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 }; struct net_proto_family netlink_family_ops = { PF_NETLINK, netlink_create }; void netlink_proto_init(struct net_proto *pro) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *ent; #endif struct sk_buff *dummy_skb; if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "netlink_proto_init: panic\n"); return; } sock_register(&netlink_family_ops); #ifdef CONFIG_PROC_FS ent = create_proc_entry("net/netlink", 0, 0); ent->read_proc = netlink_read_proc; #endif }


struct net_proto_family { int family; int (*create)(struct socket *sock, int protocol); /* These are counters for the number of different methods of each we support */ short authentication; short encryption; short encrypt_net; };


/* * The protocol list. Each protocol is registered in here. */ struct net_proto_family *net_families[NPROTO]; ... /* * This function is called by a protocol handler that wants to * advertise its address family, and have it linked into the * SOCKET module. */ int sock_register(struct net_proto_family *ops) { if (ops->family >= NPROTO) { printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); return -ENOBUFS; } net_families[ops->family]=ops; return 0; }