~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to net/tipc/config.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * net/tipc/config.c: TIPC configuration management code
 
3
 *
 
4
 * Copyright (c) 2002-2006, Ericsson AB
 
5
 * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions are met:
 
10
 *
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 * 3. Neither the names of the copyright holders nor the names of its
 
17
 *    contributors may be used to endorse or promote products derived from
 
18
 *    this software without specific prior written permission.
 
19
 *
 
20
 * Alternatively, this software may be distributed under the terms of the
 
21
 * GNU General Public License ("GPL") version 2 as published by the Free
 
22
 * Software Foundation.
 
23
 *
 
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
34
 * POSSIBILITY OF SUCH DAMAGE.
 
35
 */
 
36
 
 
37
#include "core.h"
 
38
#include "port.h"
 
39
#include "name_table.h"
 
40
#include "config.h"
 
41
 
 
42
static u32 config_port_ref;
 
43
 
 
44
static DEFINE_SPINLOCK(config_lock);
 
45
 
 
46
static const void *req_tlv_area;        /* request message TLV area */
 
47
static int req_tlv_space;               /* request message TLV area size */
 
48
static int rep_headroom;                /* reply message headroom to use */
 
49
 
 
50
 
 
51
struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
 
52
{
 
53
        struct sk_buff *buf;
 
54
 
 
55
        buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
 
56
        if (buf)
 
57
                skb_reserve(buf, rep_headroom);
 
58
        return buf;
 
59
}
 
60
 
 
61
int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
 
62
                        void *tlv_data, int tlv_data_size)
 
63
{
 
64
        struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf);
 
65
        int new_tlv_space = TLV_SPACE(tlv_data_size);
 
66
 
 
67
        if (skb_tailroom(buf) < new_tlv_space)
 
68
                return 0;
 
69
        skb_put(buf, new_tlv_space);
 
70
        tlv->tlv_type = htons(tlv_type);
 
71
        tlv->tlv_len  = htons(TLV_LENGTH(tlv_data_size));
 
72
        if (tlv_data_size && tlv_data)
 
73
                memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
 
74
        return 1;
 
75
}
 
76
 
 
77
static struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
 
78
{
 
79
        struct sk_buff *buf;
 
80
        __be32 value_net;
 
81
 
 
82
        buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
 
83
        if (buf) {
 
84
                value_net = htonl(value);
 
85
                tipc_cfg_append_tlv(buf, tlv_type, &value_net,
 
86
                                    sizeof(value_net));
 
87
        }
 
88
        return buf;
 
89
}
 
90
 
 
91
static struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
 
92
{
 
93
        return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
 
94
}
 
95
 
 
96
struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
 
97
{
 
98
        struct sk_buff *buf;
 
99
        int string_len = strlen(string) + 1;
 
100
 
 
101
        buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
 
102
        if (buf)
 
103
                tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
 
104
        return buf;
 
105
}
 
106
 
 
107
#define MAX_STATS_INFO 2000
 
108
 
 
109
static struct sk_buff *tipc_show_stats(void)
 
110
{
 
111
        struct sk_buff *buf;
 
112
        struct tlv_desc *rep_tlv;
 
113
        struct print_buf pb;
 
114
        int str_len;
 
115
        u32 value;
 
116
 
 
117
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
118
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
119
 
 
120
        value = ntohl(*(u32 *)TLV_DATA(req_tlv_area));
 
121
        if (value != 0)
 
122
                return tipc_cfg_reply_error_string("unsupported argument");
 
123
 
 
124
        buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_STATS_INFO));
 
125
        if (buf == NULL)
 
126
                return NULL;
 
127
 
 
128
        rep_tlv = (struct tlv_desc *)buf->data;
 
129
        tipc_printbuf_init(&pb, (char *)TLV_DATA(rep_tlv), MAX_STATS_INFO);
 
130
 
 
131
        tipc_printf(&pb, "TIPC version " TIPC_MOD_VER "\n");
 
132
 
 
133
        /* Use additional tipc_printf()'s to return more info ... */
 
134
 
 
135
        str_len = tipc_printbuf_validate(&pb);
 
136
        skb_put(buf, TLV_SPACE(str_len));
 
137
        TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
 
138
 
 
139
        return buf;
 
140
}
 
141
 
 
142
static struct sk_buff *cfg_enable_bearer(void)
 
143
{
 
144
        struct tipc_bearer_config *args;
 
145
 
 
146
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
 
147
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
148
 
 
149
        args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
 
150
        if (tipc_enable_bearer(args->name,
 
151
                               ntohl(args->disc_domain),
 
152
                               ntohl(args->priority)))
 
153
                return tipc_cfg_reply_error_string("unable to enable bearer");
 
154
 
 
155
        return tipc_cfg_reply_none();
 
156
}
 
157
 
 
158
static struct sk_buff *cfg_disable_bearer(void)
 
159
{
 
160
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
 
161
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
162
 
 
163
        if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
 
164
                return tipc_cfg_reply_error_string("unable to disable bearer");
 
165
 
 
166
        return tipc_cfg_reply_none();
 
167
}
 
168
 
 
169
static struct sk_buff *cfg_set_own_addr(void)
 
170
{
 
171
        u32 addr;
 
172
 
 
173
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
 
174
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
175
 
 
176
        addr = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
177
        if (addr == tipc_own_addr)
 
178
                return tipc_cfg_reply_none();
 
179
        if (!tipc_addr_node_valid(addr))
 
180
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 
181
                                                   " (node address)");
 
182
        if (tipc_mode == TIPC_NET_MODE)
 
183
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
184
                                                   " (cannot change node address once assigned)");
 
185
 
 
186
        /*
 
187
         * Must release all spinlocks before calling start_net() because
 
188
         * Linux version of TIPC calls eth_media_start() which calls
 
189
         * register_netdevice_notifier() which may block!
 
190
         *
 
191
         * Temporarily releasing the lock should be harmless for non-Linux TIPC,
 
192
         * but Linux version of eth_media_start() should really be reworked
 
193
         * so that it can be called with spinlocks held.
 
194
         */
 
195
 
 
196
        spin_unlock_bh(&config_lock);
 
197
        tipc_core_start_net(addr);
 
198
        spin_lock_bh(&config_lock);
 
199
        return tipc_cfg_reply_none();
 
200
}
 
201
 
 
202
static struct sk_buff *cfg_set_remote_mng(void)
 
203
{
 
204
        u32 value;
 
205
 
 
206
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
207
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
208
 
 
209
        value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
210
        tipc_remote_management = (value != 0);
 
211
        return tipc_cfg_reply_none();
 
212
}
 
213
 
 
214
static struct sk_buff *cfg_set_max_publications(void)
 
215
{
 
216
        u32 value;
 
217
 
 
218
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
219
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
220
 
 
221
        value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
222
        if (value != delimit(value, 1, 65535))
 
223
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 
224
                                                   " (max publications must be 1-65535)");
 
225
        tipc_max_publications = value;
 
226
        return tipc_cfg_reply_none();
 
227
}
 
228
 
 
229
static struct sk_buff *cfg_set_max_subscriptions(void)
 
230
{
 
231
        u32 value;
 
232
 
 
233
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
234
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
235
 
 
236
        value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
237
        if (value != delimit(value, 1, 65535))
 
238
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 
239
                                                   " (max subscriptions must be 1-65535");
 
240
        tipc_max_subscriptions = value;
 
241
        return tipc_cfg_reply_none();
 
242
}
 
243
 
 
244
static struct sk_buff *cfg_set_max_ports(void)
 
245
{
 
246
        u32 value;
 
247
 
 
248
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
249
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
250
        value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
251
        if (value == tipc_max_ports)
 
252
                return tipc_cfg_reply_none();
 
253
        if (value != delimit(value, 127, 65535))
 
254
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 
255
                                                   " (max ports must be 127-65535)");
 
256
        if (tipc_mode != TIPC_NOT_RUNNING)
 
257
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
258
                        " (cannot change max ports while TIPC is active)");
 
259
        tipc_max_ports = value;
 
260
        return tipc_cfg_reply_none();
 
261
}
 
262
 
 
263
static struct sk_buff *cfg_set_netid(void)
 
264
{
 
265
        u32 value;
 
266
 
 
267
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 
268
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 
269
        value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
 
270
        if (value == tipc_net_id)
 
271
                return tipc_cfg_reply_none();
 
272
        if (value != delimit(value, 1, 9999))
 
273
                return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 
274
                                                   " (network id must be 1-9999)");
 
275
        if (tipc_mode == TIPC_NET_MODE)
 
276
                return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
277
                        " (cannot change network id once TIPC has joined a network)");
 
278
        tipc_net_id = value;
 
279
        return tipc_cfg_reply_none();
 
280
}
 
281
 
 
282
struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
 
283
                                int request_space, int reply_headroom)
 
284
{
 
285
        struct sk_buff *rep_tlv_buf;
 
286
 
 
287
        spin_lock_bh(&config_lock);
 
288
 
 
289
        /* Save request and reply details in a well-known location */
 
290
 
 
291
        req_tlv_area = request_area;
 
292
        req_tlv_space = request_space;
 
293
        rep_headroom = reply_headroom;
 
294
 
 
295
        /* Check command authorization */
 
296
 
 
297
        if (likely(orig_node == tipc_own_addr)) {
 
298
                /* command is permitted */
 
299
        } else if (cmd >= 0x8000) {
 
300
                rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
301
                                                          " (cannot be done remotely)");
 
302
                goto exit;
 
303
        } else if (!tipc_remote_management) {
 
304
                rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
 
305
                goto exit;
 
306
        } else if (cmd >= 0x4000) {
 
307
                u32 domain = 0;
 
308
 
 
309
                if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
 
310
                    (domain != orig_node)) {
 
311
                        rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
 
312
                        goto exit;
 
313
                }
 
314
        }
 
315
 
 
316
        /* Call appropriate processing routine */
 
317
 
 
318
        switch (cmd) {
 
319
        case TIPC_CMD_NOOP:
 
320
                rep_tlv_buf = tipc_cfg_reply_none();
 
321
                break;
 
322
        case TIPC_CMD_GET_NODES:
 
323
                rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space);
 
324
                break;
 
325
        case TIPC_CMD_GET_LINKS:
 
326
                rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space);
 
327
                break;
 
328
        case TIPC_CMD_SHOW_LINK_STATS:
 
329
                rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space);
 
330
                break;
 
331
        case TIPC_CMD_RESET_LINK_STATS:
 
332
                rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space);
 
333
                break;
 
334
        case TIPC_CMD_SHOW_NAME_TABLE:
 
335
                rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space);
 
336
                break;
 
337
        case TIPC_CMD_GET_BEARER_NAMES:
 
338
                rep_tlv_buf = tipc_bearer_get_names();
 
339
                break;
 
340
        case TIPC_CMD_GET_MEDIA_NAMES:
 
341
                rep_tlv_buf = tipc_media_get_names();
 
342
                break;
 
343
        case TIPC_CMD_SHOW_PORTS:
 
344
                rep_tlv_buf = tipc_port_get_ports();
 
345
                break;
 
346
        case TIPC_CMD_SET_LOG_SIZE:
 
347
                rep_tlv_buf = tipc_log_resize_cmd(req_tlv_area, req_tlv_space);
 
348
                break;
 
349
        case TIPC_CMD_DUMP_LOG:
 
350
                rep_tlv_buf = tipc_log_dump();
 
351
                break;
 
352
        case TIPC_CMD_SHOW_STATS:
 
353
                rep_tlv_buf = tipc_show_stats();
 
354
                break;
 
355
        case TIPC_CMD_SET_LINK_TOL:
 
356
        case TIPC_CMD_SET_LINK_PRI:
 
357
        case TIPC_CMD_SET_LINK_WINDOW:
 
358
                rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd);
 
359
                break;
 
360
        case TIPC_CMD_ENABLE_BEARER:
 
361
                rep_tlv_buf = cfg_enable_bearer();
 
362
                break;
 
363
        case TIPC_CMD_DISABLE_BEARER:
 
364
                rep_tlv_buf = cfg_disable_bearer();
 
365
                break;
 
366
        case TIPC_CMD_SET_NODE_ADDR:
 
367
                rep_tlv_buf = cfg_set_own_addr();
 
368
                break;
 
369
        case TIPC_CMD_SET_REMOTE_MNG:
 
370
                rep_tlv_buf = cfg_set_remote_mng();
 
371
                break;
 
372
        case TIPC_CMD_SET_MAX_PORTS:
 
373
                rep_tlv_buf = cfg_set_max_ports();
 
374
                break;
 
375
        case TIPC_CMD_SET_MAX_PUBL:
 
376
                rep_tlv_buf = cfg_set_max_publications();
 
377
                break;
 
378
        case TIPC_CMD_SET_MAX_SUBSCR:
 
379
                rep_tlv_buf = cfg_set_max_subscriptions();
 
380
                break;
 
381
        case TIPC_CMD_SET_NETID:
 
382
                rep_tlv_buf = cfg_set_netid();
 
383
                break;
 
384
        case TIPC_CMD_GET_REMOTE_MNG:
 
385
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management);
 
386
                break;
 
387
        case TIPC_CMD_GET_MAX_PORTS:
 
388
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
 
389
                break;
 
390
        case TIPC_CMD_GET_MAX_PUBL:
 
391
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications);
 
392
                break;
 
393
        case TIPC_CMD_GET_MAX_SUBSCR:
 
394
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);
 
395
                break;
 
396
        case TIPC_CMD_GET_NETID:
 
397
                rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
 
398
                break;
 
399
        case TIPC_CMD_NOT_NET_ADMIN:
 
400
                rep_tlv_buf =
 
401
                        tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
 
402
                break;
 
403
        case TIPC_CMD_SET_MAX_ZONES:
 
404
        case TIPC_CMD_GET_MAX_ZONES:
 
405
        case TIPC_CMD_SET_MAX_SLAVES:
 
406
        case TIPC_CMD_GET_MAX_SLAVES:
 
407
        case TIPC_CMD_SET_MAX_CLUSTERS:
 
408
        case TIPC_CMD_GET_MAX_CLUSTERS:
 
409
        case TIPC_CMD_SET_MAX_NODES:
 
410
        case TIPC_CMD_GET_MAX_NODES:
 
411
                rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
412
                                                          " (obsolete command)");
 
413
                break;
 
414
        default:
 
415
                rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 
416
                                                          " (unknown command)");
 
417
                break;
 
418
        }
 
419
 
 
420
        /* Return reply buffer */
 
421
exit:
 
422
        spin_unlock_bh(&config_lock);
 
423
        return rep_tlv_buf;
 
424
}
 
425
 
 
426
static void cfg_named_msg_event(void *userdata,
 
427
                                u32 port_ref,
 
428
                                struct sk_buff **buf,
 
429
                                const unchar *msg,
 
430
                                u32 size,
 
431
                                u32 importance,
 
432
                                struct tipc_portid const *orig,
 
433
                                struct tipc_name_seq const *dest)
 
434
{
 
435
        struct tipc_cfg_msg_hdr *req_hdr;
 
436
        struct tipc_cfg_msg_hdr *rep_hdr;
 
437
        struct sk_buff *rep_buf;
 
438
 
 
439
        /* Validate configuration message header (ignore invalid message) */
 
440
 
 
441
        req_hdr = (struct tipc_cfg_msg_hdr *)msg;
 
442
        if ((size < sizeof(*req_hdr)) ||
 
443
            (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
 
444
            (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
 
445
                warn("Invalid configuration message discarded\n");
 
446
                return;
 
447
        }
 
448
 
 
449
        /* Generate reply for request (if can't, return request) */
 
450
 
 
451
        rep_buf = tipc_cfg_do_cmd(orig->node,
 
452
                                  ntohs(req_hdr->tcm_type),
 
453
                                  msg + sizeof(*req_hdr),
 
454
                                  size - sizeof(*req_hdr),
 
455
                                  BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
 
456
        if (rep_buf) {
 
457
                skb_push(rep_buf, sizeof(*rep_hdr));
 
458
                rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
 
459
                memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
 
460
                rep_hdr->tcm_len = htonl(rep_buf->len);
 
461
                rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
 
462
        } else {
 
463
                rep_buf = *buf;
 
464
                *buf = NULL;
 
465
        }
 
466
 
 
467
        /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */
 
468
        tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len);
 
469
}
 
470
 
 
471
int tipc_cfg_init(void)
 
472
{
 
473
        struct tipc_name_seq seq;
 
474
        int res;
 
475
 
 
476
        res = tipc_createport(NULL, TIPC_CRITICAL_IMPORTANCE,
 
477
                              NULL, NULL, NULL,
 
478
                              NULL, cfg_named_msg_event, NULL,
 
479
                              NULL, &config_port_ref);
 
480
        if (res)
 
481
                goto failed;
 
482
 
 
483
        seq.type = TIPC_CFG_SRV;
 
484
        seq.lower = seq.upper = tipc_own_addr;
 
485
        res = tipc_nametbl_publish_rsv(config_port_ref, TIPC_ZONE_SCOPE, &seq);
 
486
        if (res)
 
487
                goto failed;
 
488
 
 
489
        return 0;
 
490
 
 
491
failed:
 
492
        err("Unable to create configuration service\n");
 
493
        return res;
 
494
}
 
495
 
 
496
void tipc_cfg_stop(void)
 
497
{
 
498
        if (config_port_ref) {
 
499
                tipc_deleteport(config_port_ref);
 
500
                config_port_ref = 0;
 
501
        }
 
502
}