http://www.skyfree.org/linux/kernel_network/netlink.html

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


Reply via email to