* add config file so one can control id, timers and label assignment and

use neighbour specific options - XXX: needs documentation
* add peer authentication using TCP_MD5SIG. Interoperability tested with
  Cisco IOS
* use SLIST_FOREACH_SAFE when deleting labels instead of re-looping.
This commit is contained in:
kefren 2010-12-30 11:29:21 +00:00
parent 9231586d8c
commit e64aab24d3
11 changed files with 451 additions and 59 deletions

View File

@ -1,11 +1,12 @@
# $NetBSD: Makefile,v 1.2 2010/12/18 04:25:37 joerg Exp $
# $NetBSD: Makefile,v 1.3 2010/12/30 11:29:21 kefren Exp $
.include <bsd.own.mk>
PROG= ldpd
MAN= ldpd.8
SRCS= fsm.c \
SRCS= conffile.c \
fsm.c \
label.c \
ldp_command.c \
ldp_errors.c \

View File

@ -1,4 +1,4 @@
# $NetBSD: TODO,v 1.1 2010/12/08 07:20:14 kefren Exp $
# $NetBSD: TODO,v 1.2 2010/12/30 11:29:21 kefren Exp $
TODO
====
@ -7,6 +7,5 @@ TODO
* document better Label Distribution (downstream on demand or
unsolicited downstream), distribution control (independent or
ordered) and retention mode (liberal or conservative) - kefren
* config/options file
* future: IPv6 support. Have no infrastructure to test right
now - kefren

299
usr.sbin/ldpd/conffile.c Normal file
View File

@ -0,0 +1,299 @@
/* $NetBSD: conffile.c,v 1.1 2010/12/30 11:29:21 kefren Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Mihai Chelaru <kefren@NetBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "conffile.h"
#include "ldp_errors.h"
#define NextCommand(x) strsep(&x, " ")
#define LINEMAXSIZE 1024
extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, command_port,
min_label, max_label;
int confh;
struct in_addr conf_ldp_id;
static int conf_dispatch(char*);
static int conf_readline(char*, int);
static int checkeol(char*);
static int Fhellotime(char*);
static int Fport(char*);
static int Fholddown(char*);
static int Fkeepalive(char*);
static int Fmaxlabel(char*);
static int Fminlabel(char*);
static int Fldpid(char*);
static int Fneighbour(char*);
static int Gneighbour(struct conf_neighbour *, char *);
struct conf_func {
char com[64];
int (* func)(char *);
};
struct conf_func main_commands[] = {
{ "hello-time", Fhellotime },
{ "keepalive-time", Fkeepalive },
{ "holddown-time", Fholddown },
{ "command-port", Fport },
{ "min-label", Fminlabel },
{ "max-label", Fmaxlabel },
{ "LDP-ID", Fldpid },
{ "neighbor", Fneighbour },
{ "neighbour", Fneighbour },
{ "", NULL },
};
/*
* Parses config file
*/
int
conf_parsefile(char *fname)
{
int i;
char buf[LINEMAXSIZE + 1];
SLIST_INIT(&conei_head);
conf_ldp_id.s_addr = 0;
confh = open(fname, O_RDONLY, 0);
if (confh == -1)
return E_CONF_IO;
for (i = 1; conf_readline(buf, sizeof(buf)) >= 0; i++)
if (conf_dispatch(buf) != 0) {
close(confh);
return i;
}
close(confh);
return 0;
}
/*
* Reads a line from config file
*/
int
conf_readline(char *buf, int bufsize)
{
int i;
for (i = 0; i < bufsize; i++) {
if (read(confh, &buf[i], 1) != 1) {
if (i == 0)
return E_CONF_IO;
break;
}
if (buf[i] == '\n')
break;
if (i == 0 && isspace((int)buf[i]) != 0) {
i--;
continue;
}
}
if (i == bufsize)
return E_CONF_MEM;
buf[i] = '\0';
return i;
}
/*
* Looks for a matching command on a line
*/
int
conf_dispatch(char *line)
{
int i, last_match = -1, matched = 0;
char *command, *nline = line;
if (strlen(line) == 0 || line[0] == '#')
return E_CONF_OK;
command = NextCommand(nline);
for (i = 0; main_commands[i].func != NULL; i++)
if (strncasecmp(main_commands[i].com, command,
strlen(command)) == 0) {
matched++;
last_match = i;
}
if (matched == 0)
return E_CONF_NOMATCH;
else if (matched > 1)
return E_CONF_AMBIGUOUS;
if (checkeol(nline) != 0)
return E_CONF_PARAM;
return main_commands[last_match].func(nline);
}
/*
* Checks if a line is terminated or else if it contains
* a start block bracket. If it's semicolon terminated
* then trim it.
*/
int
checkeol(char *line)
{
if (line[strlen(line) - 1] == ';') {
line[strlen(line) - 1] = '\0';
return 0;
}
for (uint i = 0; i < strlen(line); i++)
if (line[i] == '{')
return 0;
return -1;
}
/*
* Sets hello time
*/
int
Fhellotime(char *line)
{
int ht = atoi(line);
if (ht <= 0)
return E_CONF_PARAM;
ldp_hello_time = ht;
return 0;
}
/*
* Sets command port
*/
int
Fport(char *line)
{
int cp = atoi(line);
if (cp <= 0 || cp > 65535)
return E_CONF_PARAM;
command_port = cp;
return 0;
}
/*
* Sets neighbour keepalive
*/
int
Fkeepalive(char *line)
{
int kt = atoi(line);
if (kt <= 0)
return E_CONF_PARAM;
ldp_keepalive_time = kt;
return 0;
}
/*
* Sets neighbour holddown timer
*/
int
Fholddown(char *line)
{
int hdt = atoi(line);
if (hdt <= 0)
return E_CONF_PARAM;
ldp_holddown_time = hdt;
return 0;
}
int
Fminlabel(char *line)
{
int ml = atoi(line);
if (ml <= 0)
return E_CONF_PARAM;
min_label = ml;
return 0;
}
int
Fmaxlabel(char *line)
{
int ml = atoi(line);
if (ml <= 0)
return E_CONF_PARAM;
max_label = ml;
return 0;
}
int
Fldpid(char *line)
{
if (inet_pton(AF_INET, line, &conf_ldp_id) != 1)
return E_CONF_PARAM;
return 0;
}
int
Fneighbour(char *line)
{
char *peer;
struct conf_neighbour *nei;
struct in_addr ad;
char buf[1024];
peer = NextCommand(line);
if (inet_pton(AF_INET, peer, &ad) != 1)
return E_CONF_PARAM;
nei = calloc(1, sizeof(*nei));
nei->address.s_addr = ad.s_addr;
SLIST_INSERT_HEAD(&conei_head, nei, neilist);
while(conf_readline(buf, sizeof(buf)) >= 0) {
if (buf[0] == '}')
return 0;
if (Gneighbour(nei, buf) == -1)
return -1;
}
return -1;
}
/*
* neighbour { } sub-commands
*/
int
Gneighbour(struct conf_neighbour *nei, char *line)
{
if (strncasecmp("authenticate", line, 12) == 0) {
nei->authenticate = 1;
return 0;
}
return -1;
}

56
usr.sbin/ldpd/conffile.h Normal file
View File

@ -0,0 +1,56 @@
/* $NetBSD: conffile.h,v 1.1 2010/12/30 11:29:21 kefren Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Mihai Chelaru <kefren@NetBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CONFFILE_H
#define __CONFFILE_H
#include <netinet/in.h>
#include <sys/queue.h>
#define E_CONF_OK 0
#define E_CONF_NOMATCH -1
#define E_CONF_AMBIGUOUS -2
#define E_CONF_IO -3
#define E_CONF_MEM -4
#define E_CONF_GENERIC -5
#define E_CONF_PARAM -6
struct conf_neighbour {
struct in_addr address;
int authenticate; /* RFC 2385 */
SLIST_ENTRY(conf_neighbour) neilist;
};
SLIST_HEAD(,conf_neighbour) conei_head;
int conf_parsefile(char *fname);
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: label.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
/* $NetBSD: label.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -41,6 +41,8 @@
#include "label.h"
#include "ldp_errors.h"
int min_label = MIN_LABEL, max_label = MAX_LABEL;
void
label_init()
{
@ -146,7 +148,7 @@ label_reattach_route(struct label *l, int readd)
l->label = 0;
/* Deletes pure MPLS route */
if (oldbinding >= MIN_LABEL) {
if (oldbinding >= min_label) {
u = make_mpls_union(oldbinding);
delete_route(u, NULL, FREESO);
}
@ -189,22 +191,15 @@ label_reattach_all_peer_labels(struct ldp_peer *p, int readd)
void
del_all_peer_labels(struct ldp_peer * p, int readd)
{
struct label *l;
int do_remove = 1;
struct label *l, *lnext;
while(do_remove == 1) {
do_remove = 0;
SLIST_FOREACH(l, &label_head, labels) {
SLIST_FOREACH_SAFE(l, &label_head, labels, lnext) {
if(l->p != p)
continue;
label_reattach_route(l, readd);
label_del(l);
/* remove must not interact with foreach */
SLIST_REMOVE(&label_head, l, label, labels);
do_remove = 1;
break; /* XXX: suboptimal */
}
} // while
}
/*
@ -251,11 +246,11 @@ uint32_t
get_free_local_label()
{
struct label *l;
uint32_t lbl;
int lbl;
for (lbl = MIN_LABEL; lbl <= MAX_LABEL; lbl++) {
for (lbl = min_label; lbl <= max_label; lbl++) {
SLIST_FOREACH(l, &label_head, labels)
if ((uint32_t)l->binding == lbl)
if (l->binding == lbl)
break;
if (l == NULL)
return lbl;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp.h,v 1.1 2010/12/08 07:20:14 kefren Exp $ */
/* $NetBSD: ldp.h,v 1.2 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -41,6 +41,8 @@
#define LDPD_VER "0.3.0"
#define CONFFILE "/etc/ldpd.conf"
extern char my_ldp_id[20];
#define LDP_ID my_ldp_id

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp_command.c,v 1.2 2010/12/14 21:32:43 christos Exp $ */
/* $NetBSD: ldp_command.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -51,7 +51,8 @@
#include "socketops.h"
struct com_sock csockets[MAX_COMMAND_SOCKETS];
extern int ldp_hello_time, debug_f, warn_f;
extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time,
min_label, max_label, debug_f, warn_f;
#define writestr(soc, str) write(soc, str, strlen(str))
@ -62,7 +63,7 @@ static int verify_root_pwd(char *);
static void echo_on(int s);
static void echo_off(int s);
struct com_func main_commands[] = {
static struct com_func main_commands[] = {
{ "show", show_func },
{ "set", set_func },
{ "quit", exit_func },
@ -70,7 +71,7 @@ struct com_func main_commands[] = {
{ "", NULL }
};
struct com_func show_commands[] = {
static struct com_func show_commands[] = {
{ "neighbours", show_neighbours },
{ "bindings", show_bindings },
{ "debug", show_debug },
@ -494,10 +495,10 @@ show_parameters(int s, char *recvspace)
my_ldp_id,
LDP_VERSION,
ldp_hello_time,
LDP_KEEPALIVE_TIME,
LDP_HOLDTIME,
MIN_LABEL,
MAX_LABEL);
ldp_keepalive_time,
ldp_holddown_time,
min_label,
max_label);
writestr(s, sendspace);
return 1;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ldp_peer.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
/* $NetBSD: ldp_peer.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netmpls/mpls.h>
#include <arpa/inet.h>
@ -40,6 +41,8 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "conffile.h"
#include "socketops.h"
#include "ldp_errors.h"
#include "ldp.h"
@ -48,6 +51,8 @@
#include "notifications.h"
#include "ldp_peer.h"
extern int ldp_holddown_time;
struct in_addr *myaddresses;
void
@ -68,6 +73,7 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
struct ldp_peer *p;
int s = soc;
struct sockaddr_in sa;
struct conf_neighbour *cn;
if (s < 1) {
s = socket(PF_INET, SOCK_STREAM, 0);
@ -86,11 +92,22 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
set_ttl(s);
}
/* MD5 authentication needed ? */
SLIST_FOREACH(cn, &conei_head, neilist)
if (cn->authenticate != 0 && (a->s_addr == cn->address.s_addr ||
(tradd && tradd->s_addr == cn->address.s_addr))) {
if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, &(int){1},
sizeof(int)) != 0)
fatalp("setsockopt TCP_MD5SIG: %s\n",
strerror(errno));
break;
}
/* Set the peer in CONNECTING/CONNECTED state */
p = calloc(1, sizeof(*p));
if (!p) {
fatalp("ldp_peer_new: malloc problem\n");
fatalp("ldp_peer_new: calloc problem\n");
return NULL;
}
@ -103,7 +120,7 @@ ldp_peer_new(struct in_addr * ldp_id, struct in_addr * a,
else
memcpy(&p->transport_address, a,
sizeof(struct in_addr));
p->holdtime = holdtime > LDP_HOLDTIME ? holdtime : LDP_HOLDTIME;
p->holdtime = holdtime > ldp_holddown_time ? holdtime : ldp_holddown_time;
p->socket = s;
if (soc < 1) {
p->state = LDP_PEER_CONNECTING;
@ -141,7 +158,7 @@ ldp_peer_holddown(struct ldp_peer * p)
if (p->state == LDP_PEER_ESTABLISHED)
mpls_delete_ldp_peer(p);
p->state = LDP_PEER_HOLDDOWN;
p->timeout = LDP_HOLDTIME;
p->timeout = ldp_holddown_time;
shutdown(p->socket, SHUT_RDWR);
ldp_peer_delete_all_mappings(p);
del_all_ifaddr(p);

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ldpd.8,v 1.2 2010/12/08 09:43:22 wiz Exp $
.\" $NetBSD: ldpd.8,v 1.3 2010/12/30 11:29:21 kefren Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -32,6 +32,7 @@
.Nd Label Distribution Protocol Daemon
.Sh SYNOPSIS
.Nm
.Op Fl c Ar config_file
.Op Fl DdfhW
.Op Fl p Ar port
.Sh DESCRIPTION
@ -74,6 +75,8 @@ daemon without modifications.
.Pp
The options are as follows:
.Bl -tag -width 15n
.It Fl c Ar config_file
Specifies a path to the config file. Default: /etc/ldpd.conf
.It Fl D
Enable debug mode.
.It Fl d

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.2 2010/12/08 09:43:28 wiz Exp $ */
/* $NetBSD: main.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -48,6 +48,7 @@
#include "fsm.h"
#include "ldp_errors.h"
#include "mpls_interface.h"
#include "conffile.h"
extern int ls; /* TCP listening socket */
extern int dont_catch;
@ -57,6 +58,7 @@ extern int command_socket;
extern int debug_f, warn_f, syslog_f;
extern struct sockaddr mplssockaddr;
extern struct in_addr conf_ldp_id;
void print_usage(char *myself)
{
@ -66,10 +68,15 @@ void print_usage(char *myself)
int
main(int argc, char *argv[])
{
int ch, forkres, dontfork = 0;
int ch, forkres, dontfork = 0, cpf;
char conffile[PATH_MAX + 1];
while((ch = getopt(argc, argv, "dDfhp:W")) != -1)
strlcpy(conffile, CONFFILE, sizeof(conffile));
while((ch = getopt(argc, argv, "c:dDfhp:W")) != -1)
switch(ch) {
case 'c':
strlcpy(conffile, optarg, sizeof(conffile));
break;
case 'D':
debug_f = 1;
break;
@ -98,10 +105,23 @@ main(int argc, char *argv[])
fatalp("You have to run this as ROOT\n");
return -1;
}
cpf = conf_parsefile(conffile);
if (cpf < 0 && strcmp(conffile, CONFFILE)) {
fatalp("Cannot parse config file: %s\n", conffile);
return -1;
} else if (cpf > 0) {
fatalp("Cannot parse line %d in config file\n", cpf);
return -1;
}
if (set_my_ldp_id()) {
fatalp("Cannot set LDP ID\n");
return -1;
}
if (conf_ldp_id.s_addr != 0)
strlcpy(my_ldp_id, inet_ntoa(conf_ldp_id), INET_ADDRSTRLEN);
if (mplssockaddr.sa_len == 0) {
fatalp("You need one mpls interface up and an IP "
"address set for it\n");

View File

@ -1,4 +1,4 @@
/* $NetBSD: socketops.c,v 1.2 2010/12/09 00:10:59 christos Exp $ */
/* $NetBSD: socketops.c,v 1.3 2010/12/30 11:29:21 kefren Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@ -70,6 +70,8 @@ extern struct rt_msg replay_rt[REPLAY_MAX];
extern struct com_sock csockets[MAX_COMMAND_SOCKETS];
int ldp_hello_time = LDP_HELLO_TIME;
int ldp_keepalive_time = LDP_KEEPALIVE_TIME;
int ldp_holddown_time = LDP_HOLDTIME;
void recv_pdu(int);
void send_hello_alarm(int);
@ -279,7 +281,7 @@ send_hello(void)
/* Prepare Common Hello attributes */
cht->type = htons(TLV_COMMON_HELLO);
cht->length = htons(sizeof(cht->holdtime) + sizeof(cht->res));
cht->holdtime = htons(LDP_HOLDTIME);
cht->holdtime = htons(ldp_holddown_time);
cht->res = 0;
/*
@ -456,7 +458,7 @@ void
send_hello_alarm(int unused)
{
struct ldp_peer *p;
struct hello_info *hi;
struct hello_info *hi, *hinext;
time_t t = time(NULL);
int olderrno = errno;
@ -489,7 +491,7 @@ check_peer:
} /* switch */
/* send keepalives */
if (!(t % LDP_KEEPALIVE_TIME)) {
if (!(t % ldp_keepalive_time)) {
SLIST_FOREACH(p, &ldp_peer_head, peers)
if (p->state == LDP_PEER_ESTABLISHED) {
debugp("Sending KeepAlive to %s\n",
@ -503,12 +505,9 @@ check_peer:
hi->keepalive--;
/* Check hello keepalives */
check_hello:
SLIST_FOREACH(hi, &hello_info_head, infos)
if (hi->keepalive < 1) {
SLIST_FOREACH_SAFE(hi, &hello_info_head, infos, hinext)
if (hi->keepalive < 1)
SLIST_REMOVE(&hello_info_head, hi, hello_info, infos);
goto check_hello;
}
/* Set the alarm again and bail out */
alarm(1);
@ -707,7 +706,7 @@ new_peer_connection()
return;
}
/* XXX: sa.sin_addr ain't peer LDP ID ... */
ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, LDP_HOLDTIME, s);
ldp_peer_new(&sa.sin_addr, &sa.sin_addr, NULL, ldp_holddown_time, s);
}
@ -722,7 +721,7 @@ send_initialize(struct ldp_peer * p)
ti.cs_type = htons(TLV_COMMON_SESSION);
ti.cs_len = htons(CS_LEN);
ti.cs_version = htons(LDP_VERSION);
ti.cs_keepalive = htons(2 * LDP_KEEPALIVE_TIME);
ti.cs_keepalive = htons(2 * ldp_keepalive_time);
ti.cs_adpvlim = 0;
ti.cs_maxpdulen = htons(MAX_PDU_SIZE);
ti.cs_peeraddress.s_addr = p->ldp_id.s_addr;