Commit 897522ea1c20691b6a65f32f03ae4e77e508b31c

Authored by Evgeniy Polyakov
Committed by David S. Miller
1 parent 94918ff68a

[CONNECTOR]: Add userspace example code into Documentation/connector/

I was asked several times to include userspace example code into
Documentation, so if there is no policy against it, consider attached patch
for 2.6.18. This program works with included Documentation/connector/cn_test.c
connector module.

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 206 additions and 0 deletions Side-by-side Diff

Documentation/connector/ucon.c
  1 +/*
  2 + * ucon.c
  3 + *
  4 + * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
  5 + *
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +
  22 +#include <asm/types.h>
  23 +
  24 +#include <sys/types.h>
  25 +#include <sys/socket.h>
  26 +#include <sys/poll.h>
  27 +
  28 +#include <linux/netlink.h>
  29 +#include <linux/rtnetlink.h>
  30 +
  31 +#include <arpa/inet.h>
  32 +
  33 +#include <stdio.h>
  34 +#include <stdlib.h>
  35 +#include <unistd.h>
  36 +#include <string.h>
  37 +#include <errno.h>
  38 +#include <time.h>
  39 +
  40 +#include <linux/connector.h>
  41 +
  42 +#define DEBUG
  43 +#define NETLINK_CONNECTOR 11
  44 +
  45 +#ifdef DEBUG
  46 +#define ulog(f, a...) fprintf(stdout, f, ##a)
  47 +#else
  48 +#define ulog(f, a...) do {} while (0)
  49 +#endif
  50 +
  51 +static int need_exit;
  52 +static __u32 seq;
  53 +
  54 +static int netlink_send(int s, struct cn_msg *msg)
  55 +{
  56 + struct nlmsghdr *nlh;
  57 + unsigned int size;
  58 + int err;
  59 + char buf[128];
  60 + struct cn_msg *m;
  61 +
  62 + size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
  63 +
  64 + nlh = (struct nlmsghdr *)buf;
  65 + nlh->nlmsg_seq = seq++;
  66 + nlh->nlmsg_pid = getpid();
  67 + nlh->nlmsg_type = NLMSG_DONE;
  68 + nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
  69 + nlh->nlmsg_flags = 0;
  70 +
  71 + m = NLMSG_DATA(nlh);
  72 +#if 0
  73 + ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n",
  74 + __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack);
  75 +#endif
  76 + memcpy(m, msg, sizeof(*m) + msg->len);
  77 +
  78 + err = send(s, nlh, size, 0);
  79 + if (err == -1)
  80 + ulog("Failed to send: %s [%d].\n",
  81 + strerror(errno), errno);
  82 +
  83 + return err;
  84 +}
  85 +
  86 +int main(int argc, char *argv[])
  87 +{
  88 + int s;
  89 + char buf[1024];
  90 + int len;
  91 + struct nlmsghdr *reply;
  92 + struct sockaddr_nl l_local;
  93 + struct cn_msg *data;
  94 + FILE *out;
  95 + time_t tm;
  96 + struct pollfd pfd;
  97 +
  98 + if (argc < 2)
  99 + out = stdout;
  100 + else {
  101 + out = fopen(argv[1], "a+");
  102 + if (!out) {
  103 + ulog("Unable to open %s for writing: %s\n",
  104 + argv[1], strerror(errno));
  105 + out = stdout;
  106 + }
  107 + }
  108 +
  109 + memset(buf, 0, sizeof(buf));
  110 +
  111 + s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
  112 + if (s == -1) {
  113 + perror("socket");
  114 + return -1;
  115 + }
  116 +
  117 + l_local.nl_family = AF_NETLINK;
  118 + l_local.nl_groups = 0x123; /* bitmask of requested groups */
  119 + l_local.nl_pid = 0;
  120 +
  121 + if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
  122 + perror("bind");
  123 + close(s);
  124 + return -1;
  125 + }
  126 +
  127 +#if 0
  128 + {
  129 + int on = 0x57; /* Additional group number */
  130 + setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
  131 + }
  132 +#endif
  133 + if (0) {
  134 + int i, j;
  135 +
  136 + memset(buf, 0, sizeof(buf));
  137 +
  138 + data = (struct cn_msg *)buf;
  139 +
  140 + data->id.idx = 0x123;
  141 + data->id.val = 0x456;
  142 + data->seq = seq++;
  143 + data->ack = 0;
  144 + data->len = 0;
  145 +
  146 + for (j=0; j<10; ++j) {
  147 + for (i=0; i<1000; ++i) {
  148 + len = netlink_send(s, data);
  149 + }
  150 +
  151 + ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val);
  152 + }
  153 +
  154 + return 0;
  155 + }
  156 +
  157 +
  158 + pfd.fd = s;
  159 +
  160 + while (!need_exit) {
  161 + pfd.events = POLLIN;
  162 + pfd.revents = 0;
  163 + switch (poll(&pfd, 1, -1)) {
  164 + case 0:
  165 + need_exit = 1;
  166 + break;
  167 + case -1:
  168 + if (errno != EINTR) {
  169 + need_exit = 1;
  170 + break;
  171 + }
  172 + continue;
  173 + }
  174 + if (need_exit)
  175 + break;
  176 +
  177 + memset(buf, 0, sizeof(buf));
  178 + len = recv(s, buf, sizeof(buf), 0);
  179 + if (len == -1) {
  180 + perror("recv buf");
  181 + close(s);
  182 + return -1;
  183 + }
  184 + reply = (struct nlmsghdr *)buf;
  185 +
  186 + switch (reply->nlmsg_type) {
  187 + case NLMSG_ERROR:
  188 + fprintf(out, "Error message received.\n");
  189 + fflush(out);
  190 + break;
  191 + case NLMSG_DONE:
  192 + data = (struct cn_msg *)NLMSG_DATA(reply);
  193 +
  194 + time(&tm);
  195 + fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n",
  196 + ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack);
  197 + fflush(out);
  198 + break;
  199 + default:
  200 + break;
  201 + }
  202 + }
  203 +
  204 + close(s);
  205 + return 0;
  206 +}