1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 #include <sys/un.h> /* for sockaddr_un */
25 #include "zebra/zserv.h"
26 #include "zebra/interface.h"
27 #include "zebra/debug.h"
28 #include "zebra/zebra_ptm.h"
33 #include "zebra/zebra_ptm_redistribute.h"
35 #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
36 #define ZEBRA_PTM_RECONNECT_TIME_MAX 300
39 #define PTM_HEADER_LEN 37
41 const char ZEBRA_PTM_GET_STATUS_CMD
[] = "get-status";
42 const char ZEBRA_PTM_BFD_START_CMD
[] = "start-bfd-sess";
43 const char ZEBRA_PTM_BFD_STOP_CMD
[] = "stop-bfd-sess";
45 const char ZEBRA_PTM_PORT_STR
[] = "port";
46 const char ZEBRA_PTM_CBL_STR
[] = "cbl status";
47 const char ZEBRA_PTM_PASS_STR
[] = "pass";
48 const char ZEBRA_PTM_FAIL_STR
[] = "fail";
49 const char ZEBRA_PTM_BFDSTATUS_STR
[] = "state";
50 const char ZEBRA_PTM_BFDSTATUS_UP_STR
[] = "Up";
51 const char ZEBRA_PTM_BFDSTATUS_DOWN_STR
[] = "Down";
52 const char ZEBRA_PTM_BFDDEST_STR
[] = "peer";
53 const char ZEBRA_PTM_BFDSRC_STR
[] = "local";
54 const char ZEBRA_PTM_INVALID_PORT_NAME
[] = "N/A";
55 const char ZEBRA_PTM_INVALID_SRC_IP
[] = "N/A";
57 const char ZEBRA_PTM_BFD_DST_IP_FIELD
[] = "dstIPaddr";
58 const char ZEBRA_PTM_BFD_SRC_IP_FIELD
[] = "srcIPaddr";
59 const char ZEBRA_PTM_BFD_MIN_RX_FIELD
[] = "requiredMinRx";
60 const char ZEBRA_PTM_BFD_MIN_TX_FIELD
[] = "upMinTx";
61 const char ZEBRA_PTM_BFD_DETECT_MULT_FIELD
[] = "detectMult";
62 const char ZEBRA_PTM_BFD_MULTI_HOP_FIELD
[] = "multiHop";
63 const char ZEBRA_PTM_BFD_CLIENT_FIELD
[] = "client";
64 const char ZEBRA_PTM_BFD_SEQID_FIELD
[] = "seqid";
65 const char ZEBRA_PTM_BFD_IFNAME_FIELD
[] = "ifName";
66 const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD
[] = "maxHopCnt";
68 extern struct zebra_t zebrad
;
71 int zebra_ptm_sock
= -1;
72 struct thread
*zebra_ptm_thread
= NULL
;
74 static int zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
75 int zebra_ptm_pid
= 0;
76 static ptm_lib_handle_t
*ptm_hdl
;
78 static int zebra_ptm_socket_init(void);
79 int zebra_ptm_sock_read(struct thread
*);
80 int zebra_ptm_sock_write(struct thread
*);
81 static void zebra_ptm_install_commands (void);
82 static int zebra_ptm_handle_cbl_msg(void *arg
, void *in_ctxt
);
83 static int zebra_ptm_handle_bfd_msg(void *arg
, void *in_ctxt
);
84 void zebra_bfd_peer_replay_req (void);
86 const char ZEBRA_PTM_SOCK_NAME
[] = "\0/var/run/ptmd.socket";
93 zebra_ptm_pid
= getpid();
94 zebra_ptm_install_commands();
96 sprintf(buf
, "%s", "quagga");
97 ptm_hdl
= ptm_lib_register(buf
, NULL
, zebra_ptm_handle_bfd_msg
,
98 zebra_ptm_handle_cbl_msg
);
102 zebra_ptm_connect (struct thread
*t
)
107 int len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
109 if (zebra_ptm_sock
== -1) {
110 zebra_ptm_socket_init();
114 if (zebra_ptm_sock
!= -1) {
116 zebra_bfd_peer_replay_req();
120 data
= calloc(1, len
);
122 zlog_debug("%s: Allocation of send data failed", __func__
);
125 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
126 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, "cmd", ZEBRA_PTM_GET_STATUS_CMD
);
127 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, data
, &len
);
129 zebra_ptm_thread
= thread_add_write (zebrad
.master
, zebra_ptm_sock_write
,
130 data
, zebra_ptm_sock
);
132 zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
134 zebra_ptm_reconnect_time
*= 2;
135 if (zebra_ptm_reconnect_time
> ZEBRA_PTM_RECONNECT_TIME_MAX
)
136 zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_MAX
;
138 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
, NULL
,
139 zebra_ptm_reconnect_time
);
145 DEFUN (zebra_ptm_enable
,
146 zebra_ptm_enable_cmd
,
148 "Enable neighbor check with specified topology\n")
151 struct interface
*ifp
;
155 for (ALL_LIST_ELEMENTS_RO (iflist
, i
, ifp
))
156 if (!ifp
->ptm_enable
)
159 ifp
->ptm_status
= 1; /* to bring down ports that may fail check */
162 zebra_ptm_connect(NULL
);
167 DEFUN (no_zebra_ptm_enable
,
168 no_zebra_ptm_enable_cmd
,
171 "Enable neighbor check with specified topology\n")
174 struct interface
*ifp
;
178 for (ALL_LIST_ELEMENTS_RO (iflist
, i
, ifp
))
182 if (!if_is_operative(ifp
))
186 if (if_is_operative (ifp
) && send_linkup
) {
187 zlog_debug ("%s: Bringing up interface %s", __func__
,
198 zebra_ptm_write (struct vty
*vty
)
201 vty_out (vty
, "ptm-enable%s", VTY_NEWLINE
);
207 zebra_ptm_socket_init (void)
211 struct sockaddr_un addr
;
215 sock
= socket (PF_UNIX
, (SOCK_STREAM
| SOCK_NONBLOCK
), 0);
219 /* Make server socket. */
220 memset (&addr
, 0, sizeof (struct sockaddr_un
));
221 addr
.sun_family
= AF_UNIX
;
222 memcpy (&addr
.sun_path
, ZEBRA_PTM_SOCK_NAME
,
223 sizeof(ZEBRA_PTM_SOCK_NAME
));
225 ret
= connect(sock
, (struct sockaddr
*) &addr
,
226 sizeof (addr
.sun_family
)+sizeof (ZEBRA_PTM_SOCK_NAME
)-1);
229 zlog_warn("%s: Unable to connect to socket %s [%s]",
230 __func__
, ZEBRA_PTM_SOCK_NAME
, safe_strerror(errno
));
234 zlog_debug ("%s: connection to ptm socket %s succeeded",
235 __func__
, ZEBRA_PTM_SOCK_NAME
);
236 zebra_ptm_sock
= sock
;
241 zebra_ptm_install_commands (void)
243 install_element (CONFIG_NODE
, &zebra_ptm_enable_cmd
);
244 install_element (CONFIG_NODE
, &no_zebra_ptm_enable_cmd
);
247 /* BFD session goes down, send message to the protocols. */
249 if_bfd_session_down (struct interface
*ifp
, struct prefix
*dp
, struct prefix
*sp
)
251 if (IS_ZEBRA_DEBUG_EVENT
)
253 char buf
[2][INET6_ADDRSTRLEN
];
257 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s",
258 inet_ntop (dp
->family
, &dp
->u
.prefix
, buf
, INET6_ADDRSTRLEN
),
259 dp
->prefixlen
, ifp
->name
);
263 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d "
265 inet_ntop (dp
->family
, &dp
->u
.prefix
, buf
[0], INET6_ADDRSTRLEN
),
267 inet_ntop (sp
->family
, &sp
->u
.prefix
, buf
[1], INET6_ADDRSTRLEN
),
272 zebra_interface_bfd_update (ifp
, dp
, sp
);
276 zebra_ptm_handle_bfd_msg(void *arg
, void *in_ctxt
)
278 struct interface
*ifp
= NULL
;
283 struct prefix dest_prefix
;
284 struct prefix src_prefix
;
286 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_PORT_STR
, port_str
);
288 if (port_str
[0] == '\0') {
289 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
294 if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME
, port_str
)) {
295 ifp
= if_lookup_by_name(port_str
);
298 zlog_err("%s: %s not found in interface list", __func__
, port_str
);
303 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDSTATUS_STR
, bfdst_str
);
305 if (bfdst_str
[0] == '\0') {
309 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDDEST_STR
, dest_str
);
311 if (dest_str
[0] == '\0') {
312 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
313 ZEBRA_PTM_BFDDEST_STR
);
317 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_BFDSRC_STR
, src_str
);
319 if (src_str
[0] == '\0') {
320 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
321 ZEBRA_PTM_BFDSRC_STR
);
325 zlog_debug("%s: Recv Port [%s] bfd status [%s] peer [%s] local [%s]",
326 __func__
, port_str
, bfdst_str
, dest_str
, src_str
);
328 /* we only care if bfd session goes down */
329 if (!strcmp (bfdst_str
, ZEBRA_PTM_BFDSTATUS_DOWN_STR
)) {
330 if (inet_pton(AF_INET
, dest_str
, &dest_prefix
.u
.prefix4
) > 0) {
331 dest_prefix
.family
= AF_INET
;
332 dest_prefix
.prefixlen
= IPV4_MAX_PREFIXLEN
;
335 else if (inet_pton(AF_INET6
, dest_str
, &dest_prefix
.u
.prefix6
) > 0) {
336 dest_prefix
.family
= AF_INET6
;
337 dest_prefix
.prefixlen
= IPV6_MAX_PREFIXLEN
;
339 #endif /* HAVE_IPV6 */
341 zlog_err("%s: Peer addr %s not found", __func__
,
346 memset(&src_prefix
, 0, sizeof(struct prefix
));
347 if (strcmp(ZEBRA_PTM_INVALID_SRC_IP
, src_str
)) {
348 if (inet_pton(AF_INET
, src_str
, &src_prefix
.u
.prefix4
) > 0) {
349 src_prefix
.family
= AF_INET
;
350 src_prefix
.prefixlen
= IPV4_MAX_PREFIXLEN
;
353 else if (inet_pton(AF_INET6
, src_str
, &src_prefix
.u
.prefix6
) > 0) {
354 src_prefix
.family
= AF_INET6
;
355 src_prefix
.prefixlen
= IPV6_MAX_PREFIXLEN
;
357 #endif /* HAVE_IPV6 */
359 zlog_err("%s: Local addr %s not found", __func__
,
365 if_bfd_session_down(ifp
, &dest_prefix
, &src_prefix
);
372 zebra_ptm_handle_cbl_msg(void *arg
, void *in_ctxt
)
374 struct interface
*ifp
;
378 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_PORT_STR
, port_str
);
380 if (port_str
[0] == '\0') {
381 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
386 ptm_lib_find_key_in_msg(in_ctxt
, ZEBRA_PTM_CBL_STR
, cbl_str
);
388 if (cbl_str
[0] == '\0') {
389 zlog_debug("%s: Key %s not found in PTM msg", __func__
,
394 zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__
,
397 ifp
= if_lookup_by_name(port_str
);
400 zlog_err("%s: %s not found in interface list", __func__
, port_str
);
404 if (!strcmp(cbl_str
, ZEBRA_PTM_PASS_STR
) && (!ifp
->ptm_status
)) {
406 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
))
408 } else if (!strcmp (cbl_str
, ZEBRA_PTM_FAIL_STR
) && (ifp
->ptm_status
)) {
410 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
))
418 zebra_ptm_sock_write (struct thread
*thread
)
424 sock
= THREAD_FD (thread
);
425 data
= THREAD_ARG (thread
);
432 nbytes
= send(sock
, data
, strlen(data
), 0);
435 if (errno
&& errno
!= EWOULDBLOCK
&& errno
!= EAGAIN
) {
436 zlog_warn ("%s routing socket error: %s", __func__
,
437 safe_strerror (errno
));
439 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
,
440 NULL
, zebra_ptm_reconnect_time
);
445 zlog_debug ("%s: Sent message (%d) %s", __func__
, strlen(data
), data
);
446 zebra_ptm_thread
= thread_add_read (zebrad
.master
, zebra_ptm_sock_read
,
453 zebra_ptm_sock_read (struct thread
*thread
)
460 sock
= THREAD_FD (thread
);
465 /* PTM communicates in CSV format */
467 rcvptr
= calloc(1, ZEBRA_PTM_MAX_SOCKBUF
);
469 rc
= ptm_lib_process_msg(ptm_hdl
, sock
, rcvptr
, ZEBRA_PTM_MAX_SOCKBUF
,
476 if (((rc
== 0) && !errno
) || (errno
&& (errno
!= EWOULDBLOCK
) && (errno
!= EAGAIN
))) {
477 zlog_warn ("%s routing socket error: %s(%d) bytes %d", __func__
,
478 safe_strerror (errno
), errno
, rc
);
480 close (zebra_ptm_sock
);
482 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
,
483 NULL
, zebra_ptm_reconnect_time
);
489 zebra_ptm_thread
= thread_add_read (zebrad
.master
, zebra_ptm_sock_read
,
495 /* BFD peer/dst register/update */
497 zebra_ptm_bfd_dst_register (struct zserv
*client
, int sock
, u_short length
,
505 u_char multi_hop_cnt
;
507 unsigned int min_rx_timer
;
508 unsigned int min_tx_timer
;
509 char if_name
[INTERFACE_NAMSIZ
];
512 char buf
[INET6_ADDRSTRLEN
];
514 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
516 if (command
== ZEBRA_BFD_DEST_UPDATE
)
517 client
->bfd_peer_upd8_cnt
++;
519 client
->bfd_peer_add_cnt
++;
521 zlog_debug("bfd_dst_register msg from client %s: length=%d",
522 zebra_route_string(client
->proto
), length
);
524 if (zebra_ptm_sock
== -1)
526 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
,
527 NULL
, zebra_ptm_reconnect_time
);
531 data
= calloc(1, data_len
);
534 zlog_debug("%s: Allocation of send data failed", __func__
);
538 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
539 sprintf(tmp_buf
, "%s", ZEBRA_PTM_BFD_START_CMD
);
540 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, "cmd", tmp_buf
);
541 sprintf(tmp_buf
, "quagga");
542 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
544 sprintf(tmp_buf
, "%d", zebra_ptm_pid
);
545 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_SEQID_FIELD
,
550 dst_p
.family
= stream_getw(s
);
552 if (dst_p
.family
== AF_INET
)
553 dst_p
.prefixlen
= IPV4_MAX_BYTELEN
;
555 dst_p
.prefixlen
= IPV6_MAX_BYTELEN
;
557 stream_get(&dst_p
.u
.prefix
, s
, dst_p
.prefixlen
);
558 if (dst_p
.family
== AF_INET
)
560 inet_ntop(AF_INET
, &dst_p
.u
.prefix4
, buf
, sizeof(buf
));
561 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_DST_IP_FIELD
, buf
);
566 inet_ntop(AF_INET6
, &dst_p
.u
.prefix6
, buf
, sizeof(buf
));
567 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_DST_IP_FIELD
, buf
);
569 #endif /* HAVE_IPV6 */
571 min_rx_timer
= stream_getl(s
);
572 sprintf(tmp_buf
, "%d", min_rx_timer
);
573 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MIN_RX_FIELD
,
575 min_tx_timer
= stream_getl(s
);
576 sprintf(tmp_buf
, "%d", min_tx_timer
);
577 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MIN_TX_FIELD
,
579 detect_mul
= stream_getc(s
);
580 sprintf(tmp_buf
, "%d", detect_mul
);
581 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_DETECT_MULT_FIELD
,
584 multi_hop
= stream_getc(s
);
587 sprintf(tmp_buf
, "%d", 1);
588 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MULTI_HOP_FIELD
,
590 src_p
.family
= stream_getw(s
);
592 if (src_p
.family
== AF_INET
)
593 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
595 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
597 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
598 if (src_p
.family
== AF_INET
)
600 inet_ntop(AF_INET
, &src_p
.u
.prefix4
, buf
, sizeof(buf
));
601 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
602 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
607 inet_ntop(AF_INET6
, &src_p
.u
.prefix6
, buf
, sizeof(buf
));
608 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
609 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
611 #endif /* HAVE_IPV6 */
613 multi_hop_cnt
= stream_getc(s
);
614 sprintf(tmp_buf
, "%d", multi_hop_cnt
);
615 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD
,
621 if (dst_p
.family
== AF_INET6
)
623 src_p
.family
= stream_getw(s
);
625 if (src_p
.family
== AF_INET
)
626 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
628 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
630 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
631 if (src_p
.family
== AF_INET
)
633 inet_ntop(AF_INET
, &src_p
.u
.prefix4
, buf
, sizeof(buf
));
634 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
635 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
639 inet_ntop(AF_INET6
, &src_p
.u
.prefix6
, buf
, sizeof(buf
));
640 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
641 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
644 #endif /* HAVE_IPV6 */
645 len
= stream_getc(s
);
646 stream_get(if_name
, s
, len
);
649 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_IFNAME_FIELD
,
653 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, data
, &data_len
);
654 zebra_ptm_thread
= thread_add_write (zebrad
.master
, zebra_ptm_sock_write
,
655 data
, zebra_ptm_sock
);
659 /* BFD peer/dst deregister */
661 zebra_ptm_bfd_dst_deregister (struct zserv
*client
, int sock
, u_short length
)
668 char if_name
[INTERFACE_NAMSIZ
];
670 char buf
[INET6_ADDRSTRLEN
];
672 int data_len
= ZEBRA_PTM_SEND_MAX_SOCKBUF
;
675 client
->bfd_peer_del_cnt
++;
677 zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
678 zebra_route_string(client
->proto
), length
);
680 if (zebra_ptm_sock
== -1)
682 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
,
683 NULL
, zebra_ptm_reconnect_time
);
687 data
= calloc(1, data_len
);
690 zlog_debug("%s: Allocation of send data failed", __func__
);
694 ptm_lib_init_msg(ptm_hdl
, 0, PTMLIB_MSG_TYPE_CMD
, NULL
, &out_ctxt
);
696 sprintf(tmp_buf
, "%s", ZEBRA_PTM_BFD_STOP_CMD
);
697 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, "cmd", tmp_buf
);
699 sprintf(tmp_buf
, "%s", "quagga");
700 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_CLIENT_FIELD
,
703 sprintf(tmp_buf
, "%d", zebra_ptm_pid
);
704 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_SEQID_FIELD
,
709 dst_p
.family
= stream_getw(s
);
711 if (dst_p
.family
== AF_INET
)
712 dst_p
.prefixlen
= IPV4_MAX_BYTELEN
;
714 dst_p
.prefixlen
= IPV6_MAX_BYTELEN
;
716 stream_get(&dst_p
.u
.prefix
, s
, dst_p
.prefixlen
);
717 if (dst_p
.family
== AF_INET
)
719 inet_ntop(AF_INET
, &dst_p
.u
.prefix4
, buf
, sizeof(buf
));
720 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_DST_IP_FIELD
, buf
);
725 inet_ntop(AF_INET6
, &dst_p
.u
.prefix6
, buf
, sizeof(buf
));
726 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_DST_IP_FIELD
, buf
);
728 #endif /* HAVE_IPV6 */
730 multi_hop
= stream_getc(s
);
733 sprintf(tmp_buf
, "%d", 1);
734 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_MULTI_HOP_FIELD
,
737 src_p
.family
= stream_getw(s
);
739 if (src_p
.family
== AF_INET
)
740 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
742 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
744 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
745 if (src_p
.family
== AF_INET
)
747 inet_ntop(AF_INET
, &src_p
.u
.prefix4
, buf
, sizeof(buf
));
748 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
749 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
754 inet_ntop(AF_INET6
, &src_p
.u
.prefix6
, buf
, sizeof(buf
));
755 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
756 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
758 #endif /* HAVE_IPV6 */
763 if (dst_p
.family
== AF_INET6
)
765 src_p
.family
= stream_getw(s
);
767 if (src_p
.family
== AF_INET
)
768 src_p
.prefixlen
= IPV4_MAX_BYTELEN
;
770 src_p
.prefixlen
= IPV6_MAX_BYTELEN
;
772 stream_get(&src_p
.u
.prefix
, s
, src_p
.prefixlen
);
773 if (src_p
.family
== AF_INET
)
775 inet_ntop(AF_INET
, &src_p
.u
.prefix4
, buf
, sizeof(buf
));
776 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
777 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
781 inet_ntop(AF_INET6
, &src_p
.u
.prefix6
, buf
, sizeof(buf
));
782 ptm_lib_append_msg(ptm_hdl
, out_ctxt
,
783 ZEBRA_PTM_BFD_SRC_IP_FIELD
, buf
);
786 #endif /* HAVE_IPV6 */
788 len
= stream_getc(s
);
789 stream_get(if_name
, s
, len
);
792 ptm_lib_append_msg(ptm_hdl
, out_ctxt
, ZEBRA_PTM_BFD_IFNAME_FIELD
,
796 ptm_lib_complete_msg(ptm_hdl
, out_ctxt
, data
, &data_len
);
797 zebra_ptm_thread
= thread_add_write (zebrad
.master
, zebra_ptm_sock_write
,
798 data
, zebra_ptm_sock
);