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

NETLINK_FIREWALL

Receive packets sent by IPv4 firewall

NETLINK_ARPD

Manage ARP table from user space

NETLINK_ROUTE6

IPv6 routing table update

NETLINK_IP6_FW

Currently not implemented

NETLINK_TAPBASE

Ethertap device

NETLINK_SKIP

Reserved for ENskip

Welcome to the dungeon of Linux networking code!

init/main.c/do_basic_setup()

  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.

init/main.c

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(); ...

net/socket.c/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.. */

net/socket.c

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 }

net/socket.c/proto_init()

  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.

net/socket.c

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... */ }

net/protocols.c

/* * 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 */ };

net/netlink/af_netlink.c

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 }

include/linux/net.h

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; };

net/socket.c

/* * 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; }