]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_ptm.c
This patch changes ospfd from only listening mode for BFD status updates to interacti...
[mirror_frr.git] / zebra / zebra_ptm.c
1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 * 02111-1307, USA.
20 */
21
22 #include <zebra.h>
23 #include <sys/un.h> /* for sockaddr_un */
24 #include <net/if.h>
25 #include "zebra/zserv.h"
26 #include "zebra/interface.h"
27 #include "zebra/debug.h"
28 #include "zebra/zebra_ptm.h"
29 #include "if.h"
30 #include "command.h"
31 #include "stream.h"
32 #include "ptm_lib.h"
33 #include "zebra/zebra_ptm_redistribute.h"
34
35 #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
36 #define ZEBRA_PTM_RECONNECT_TIME_MAX 300
37
38 #define PTM_MSG_LEN 4
39 #define PTM_HEADER_LEN 37
40
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";
44
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";
56
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";
67
68 extern struct zebra_t zebrad;
69 int ptm_enable;
70
71 int zebra_ptm_sock = -1;
72 struct thread *zebra_ptm_thread = NULL;
73
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;
77
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);
85
86 const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket";
87
88 void
89 zebra_ptm_init (void)
90 {
91 char buf[64];
92
93 zebra_ptm_pid = getpid();
94 zebra_ptm_install_commands();
95
96 sprintf(buf, "%s", "quagga");
97 ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_bfd_msg,
98 zebra_ptm_handle_cbl_msg);
99 }
100
101 int
102 zebra_ptm_connect (struct thread *t)
103 {
104 int init = 0;
105 char *data;
106 void *out_ctxt;
107 int len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
108
109 if (zebra_ptm_sock == -1) {
110 zebra_ptm_socket_init();
111 init = 1;
112 }
113
114 if (zebra_ptm_sock != -1) {
115 if (init) {
116 zebra_bfd_peer_replay_req();
117 }
118
119 if (ptm_enable) {
120 data = calloc(1, len);
121 if (!data) {
122 zlog_debug("%s: Allocation of send data failed", __func__);
123 return -1;
124 }
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);
128
129 zebra_ptm_thread = thread_add_write (zebrad.master, zebra_ptm_sock_write,
130 data, zebra_ptm_sock);
131 }
132 zebra_ptm_reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
133 } else {
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;
137
138 zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL,
139 zebra_ptm_reconnect_time);
140 }
141
142 return(errno);
143 }
144
145 DEFUN (zebra_ptm_enable,
146 zebra_ptm_enable_cmd,
147 "ptm-enable",
148 "Enable neighbor check with specified topology\n")
149 {
150 struct listnode *i;
151 struct interface *ifp;
152
153 ptm_enable = 1;
154
155 for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
156 if (!ifp->ptm_enable)
157 {
158 ifp->ptm_enable = 1;
159 ifp->ptm_status = 1; /* to bring down ports that may fail check */
160 }
161
162 zebra_ptm_connect(NULL);
163
164 return CMD_SUCCESS;
165 }
166
167 DEFUN (no_zebra_ptm_enable,
168 no_zebra_ptm_enable_cmd,
169 "no ptm-enable",
170 NO_STR
171 "Enable neighbor check with specified topology\n")
172 {
173 struct listnode *i;
174 struct interface *ifp;
175 int send_linkup;
176
177 ptm_enable = 0;
178 for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp))
179 {
180 if (ifp->ptm_enable)
181 {
182 if (!if_is_operative(ifp))
183 send_linkup = 1;
184
185 ifp->ptm_enable = 0;
186 if (if_is_operative (ifp) && send_linkup) {
187 zlog_debug ("%s: Bringing up interface %s", __func__,
188 ifp->name);
189 if_up (ifp);
190 }
191 }
192 }
193
194 return CMD_SUCCESS;
195 }
196
197 void
198 zebra_ptm_write (struct vty *vty)
199 {
200 if (ptm_enable)
201 vty_out (vty, "ptm-enable%s", VTY_NEWLINE);
202
203 return;
204 }
205
206 static int
207 zebra_ptm_socket_init (void)
208 {
209 int ret;
210 int sock;
211 struct sockaddr_un addr;
212
213 zebra_ptm_sock = -1;
214
215 sock = socket (PF_UNIX, (SOCK_STREAM | SOCK_NONBLOCK), 0);
216 if (sock < 0)
217 return -1;
218
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));
224
225 ret = connect(sock, (struct sockaddr *) &addr,
226 sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1);
227 if (ret < 0)
228 {
229 zlog_warn("%s: Unable to connect to socket %s [%s]",
230 __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno));
231 close (sock);
232 return -1;
233 }
234 zlog_debug ("%s: connection to ptm socket %s succeeded",
235 __func__, ZEBRA_PTM_SOCK_NAME);
236 zebra_ptm_sock = sock;
237 return sock;
238 }
239
240 static void
241 zebra_ptm_install_commands (void)
242 {
243 install_element (CONFIG_NODE, &zebra_ptm_enable_cmd);
244 install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd);
245 }
246
247 /* BFD session goes down, send message to the protocols. */
248 void
249 if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp)
250 {
251 if (IS_ZEBRA_DEBUG_EVENT)
252 {
253 char buf[2][INET6_ADDRSTRLEN];
254
255 if (ifp)
256 {
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);
260 }
261 else
262 {
263 zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d "
264 "with src %s/%d",
265 inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN),
266 dp->prefixlen,
267 inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN),
268 sp->prefixlen);
269 }
270 }
271
272 zebra_interface_bfd_update (ifp, dp, sp);
273 }
274
275 static int
276 zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt)
277 {
278 struct interface *ifp = NULL;
279 char port_str[128];
280 char bfdst_str[32];
281 char dest_str[64];
282 char src_str[64];
283 struct prefix dest_prefix;
284 struct prefix src_prefix;
285
286 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str);
287
288 if (port_str[0] == '\0') {
289 zlog_debug("%s: Key %s not found in PTM msg", __func__,
290 ZEBRA_PTM_PORT_STR);
291 return -1;
292 }
293
294 if (strcmp(ZEBRA_PTM_INVALID_PORT_NAME, port_str)) {
295 ifp = if_lookup_by_name(port_str);
296
297 if (!ifp) {
298 zlog_err("%s: %s not found in interface list", __func__, port_str);
299 return -1;
300 }
301 }
302
303 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str);
304
305 if (bfdst_str[0] == '\0') {
306 return -1;
307 }
308
309 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDDEST_STR, dest_str);
310
311 if (dest_str[0] == '\0') {
312 zlog_debug("%s: Key %s not found in PTM msg", __func__,
313 ZEBRA_PTM_BFDDEST_STR);
314 return -1;
315 }
316
317 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSRC_STR, src_str);
318
319 if (src_str[0] == '\0') {
320 zlog_debug("%s: Key %s not found in PTM msg", __func__,
321 ZEBRA_PTM_BFDSRC_STR);
322 return -1;
323 }
324
325 zlog_debug("%s: Recv Port [%s] bfd status [%s] peer [%s] local [%s]",
326 __func__, port_str, bfdst_str, dest_str, src_str);
327
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;
333 }
334 #ifdef HAVE_IPV6
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;
338 }
339 #endif /* HAVE_IPV6 */
340 else {
341 zlog_err("%s: Peer addr %s not found", __func__,
342 dest_str);
343 return -1;
344 }
345
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;
351 }
352 #ifdef HAVE_IPV6
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;
356 }
357 #endif /* HAVE_IPV6 */
358 else {
359 zlog_err("%s: Local addr %s not found", __func__,
360 src_str);
361 return -1;
362 }
363 }
364
365 if_bfd_session_down(ifp, &dest_prefix, &src_prefix);
366 }
367
368 return 0;
369 }
370
371 static int
372 zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt)
373 {
374 struct interface *ifp;
375 char cbl_str[32];
376 char port_str[128];
377
378 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str);
379
380 if (port_str[0] == '\0') {
381 zlog_debug("%s: Key %s not found in PTM msg", __func__,
382 ZEBRA_PTM_PORT_STR);
383 return 0;
384 }
385
386 ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CBL_STR, cbl_str);
387
388 if (cbl_str[0] == '\0') {
389 zlog_debug("%s: Key %s not found in PTM msg", __func__,
390 ZEBRA_PTM_CBL_STR);
391 return 0;
392 }
393
394 zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__,
395 port_str, cbl_str);
396
397 ifp = if_lookup_by_name(port_str);
398
399 if (!ifp) {
400 zlog_err("%s: %s not found in interface list", __func__, port_str);
401 return -1;
402 }
403
404 if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) && (!ifp->ptm_status)) {
405 ifp->ptm_status = 1;
406 if (ifp->ptm_enable && if_is_no_ptm_operative (ifp))
407 if_up (ifp);
408 } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) && (ifp->ptm_status)) {
409 ifp->ptm_status = 0;
410 if (ifp->ptm_enable && if_is_no_ptm_operative (ifp))
411 if_down (ifp);
412 }
413
414 return 0;
415 }
416
417 int
418 zebra_ptm_sock_write (struct thread *thread)
419 {
420 int sock;
421 int nbytes;
422 char *data;
423
424 sock = THREAD_FD (thread);
425 data = THREAD_ARG (thread);
426
427 if (sock == -1)
428 return -1;
429
430 errno = 0;
431
432 nbytes = send(sock, data, strlen(data), 0);
433
434 if (nbytes <= 0) {
435 if (errno && errno != EWOULDBLOCK && errno != EAGAIN) {
436 zlog_warn ("%s routing socket error: %s", __func__,
437 safe_strerror (errno));
438 zebra_ptm_sock = -1;
439 zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect,
440 NULL, zebra_ptm_reconnect_time);
441 return (-1);
442 }
443 }
444
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,
447 NULL, sock);
448 free (data);
449 return(0);
450 }
451
452 int
453 zebra_ptm_sock_read (struct thread *thread)
454 {
455 int sock, done = 0;
456 int rc;
457 char *rcvptr;
458
459 errno = 0;
460 sock = THREAD_FD (thread);
461
462 if (sock == -1)
463 return -1;
464
465 /* PTM communicates in CSV format */
466 while(!done) {
467 rcvptr = calloc(1, ZEBRA_PTM_MAX_SOCKBUF);
468
469 rc = ptm_lib_process_msg(ptm_hdl, sock, rcvptr, ZEBRA_PTM_MAX_SOCKBUF,
470 NULL);
471 if (rc <= 0)
472 break;
473 }
474
475 if (rc <= 0) {
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);
479
480 close (zebra_ptm_sock);
481 zebra_ptm_sock = -1;
482 zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect,
483 NULL, zebra_ptm_reconnect_time);
484 return (-1);
485 }
486 }
487
488 free(rcvptr);
489 zebra_ptm_thread = thread_add_read (zebrad.master, zebra_ptm_sock_read,
490 NULL, sock);
491
492 return 0;
493 }
494
495 /* BFD peer/dst register/update */
496 int
497 zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
498 int command)
499 {
500 char *data;
501 struct stream *s;
502 struct prefix src_p;
503 struct prefix dst_p;
504 u_char multi_hop;
505 u_char multi_hop_cnt;
506 u_char detect_mul;
507 unsigned int min_rx_timer;
508 unsigned int min_tx_timer;
509 char if_name[INTERFACE_NAMSIZ];
510 u_char len;
511 void *out_ctxt;
512 char buf[INET6_ADDRSTRLEN];
513 char tmp_buf[64];
514 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
515
516 if (command == ZEBRA_BFD_DEST_UPDATE)
517 client->bfd_peer_upd8_cnt++;
518 else
519 client->bfd_peer_add_cnt++;
520
521 zlog_debug("bfd_dst_register msg from client %s: length=%d",
522 zebra_route_string(client->proto), length);
523
524 if (zebra_ptm_sock == -1)
525 {
526 zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect,
527 NULL, zebra_ptm_reconnect_time);
528 return -1;
529 }
530
531 data = calloc(1, data_len);
532 if (!data)
533 {
534 zlog_debug("%s: Allocation of send data failed", __func__);
535 return -1;
536 }
537
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,
543 tmp_buf);
544 sprintf(tmp_buf, "%d", zebra_ptm_pid);
545 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
546 tmp_buf);
547
548 s = client->ibuf;
549
550 dst_p.family = stream_getw(s);
551
552 if (dst_p.family == AF_INET)
553 dst_p.prefixlen = IPV4_MAX_BYTELEN;
554 else
555 dst_p.prefixlen = IPV6_MAX_BYTELEN;
556
557 stream_get(&dst_p.u.prefix, s, dst_p.prefixlen);
558 if (dst_p.family == AF_INET)
559 {
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);
562 }
563 #ifdef HAVE_IPV6
564 else
565 {
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);
568 }
569 #endif /* HAVE_IPV6 */
570
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,
574 tmp_buf);
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,
578 tmp_buf);
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,
582 tmp_buf);
583
584 multi_hop = stream_getc(s);
585 if (multi_hop)
586 {
587 sprintf(tmp_buf, "%d", 1);
588 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD,
589 tmp_buf);
590 src_p.family = stream_getw(s);
591
592 if (src_p.family == AF_INET)
593 src_p.prefixlen = IPV4_MAX_BYTELEN;
594 else
595 src_p.prefixlen = IPV6_MAX_BYTELEN;
596
597 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
598 if (src_p.family == AF_INET)
599 {
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);
603 }
604 #ifdef HAVE_IPV6
605 else
606 {
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);
610 }
611 #endif /* HAVE_IPV6 */
612
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,
616 tmp_buf);
617 }
618 else
619 {
620 #ifdef HAVE_IPV6
621 if (dst_p.family == AF_INET6)
622 {
623 src_p.family = stream_getw(s);
624
625 if (src_p.family == AF_INET)
626 src_p.prefixlen = IPV4_MAX_BYTELEN;
627 else
628 src_p.prefixlen = IPV6_MAX_BYTELEN;
629
630 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
631 if (src_p.family == AF_INET)
632 {
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);
636 }
637 else
638 {
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);
642 }
643 }
644 #endif /* HAVE_IPV6 */
645 len = stream_getc(s);
646 stream_get(if_name, s, len);
647 if_name[len] = '\0';
648
649 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD,
650 if_name);
651 }
652
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);
656 return 0;
657 }
658
659 /* BFD peer/dst deregister */
660 int
661 zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length)
662 {
663 char *data;
664 struct stream *s;
665 struct prefix src_p;
666 struct prefix dst_p;
667 u_char multi_hop;
668 char if_name[INTERFACE_NAMSIZ];
669 u_char len;
670 char buf[INET6_ADDRSTRLEN];
671 char tmp_buf[64];
672 int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
673 void *out_ctxt;
674
675 client->bfd_peer_del_cnt++;
676
677 zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
678 zebra_route_string(client->proto), length);
679
680 if (zebra_ptm_sock == -1)
681 {
682 zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect,
683 NULL, zebra_ptm_reconnect_time);
684 return -1;
685 }
686
687 data = calloc(1, data_len);
688 if (!data)
689 {
690 zlog_debug("%s: Allocation of send data failed", __func__);
691 return -1;
692 }
693
694 ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
695
696 sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD);
697 ptm_lib_append_msg(ptm_hdl, out_ctxt, "cmd", tmp_buf);
698
699 sprintf(tmp_buf, "%s", "quagga");
700 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
701 tmp_buf);
702
703 sprintf(tmp_buf, "%d", zebra_ptm_pid);
704 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD,
705 tmp_buf);
706
707 s = client->ibuf;
708
709 dst_p.family = stream_getw(s);
710
711 if (dst_p.family == AF_INET)
712 dst_p.prefixlen = IPV4_MAX_BYTELEN;
713 else
714 dst_p.prefixlen = IPV6_MAX_BYTELEN;
715
716 stream_get(&dst_p.u.prefix, s, dst_p.prefixlen);
717 if (dst_p.family == AF_INET)
718 {
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);
721 }
722 #ifdef HAVE_IPV6
723 else
724 {
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);
727 }
728 #endif /* HAVE_IPV6 */
729
730 multi_hop = stream_getc(s);
731 if (multi_hop)
732 {
733 sprintf(tmp_buf, "%d", 1);
734 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MULTI_HOP_FIELD,
735 tmp_buf);
736
737 src_p.family = stream_getw(s);
738
739 if (src_p.family == AF_INET)
740 src_p.prefixlen = IPV4_MAX_BYTELEN;
741 else
742 src_p.prefixlen = IPV6_MAX_BYTELEN;
743
744 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
745 if (src_p.family == AF_INET)
746 {
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);
750 }
751 #ifdef HAVE_IPV6
752 else
753 {
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);
757 }
758 #endif /* HAVE_IPV6 */
759 }
760 else
761 {
762 #ifdef HAVE_IPV6
763 if (dst_p.family == AF_INET6)
764 {
765 src_p.family = stream_getw(s);
766
767 if (src_p.family == AF_INET)
768 src_p.prefixlen = IPV4_MAX_BYTELEN;
769 else
770 src_p.prefixlen = IPV6_MAX_BYTELEN;
771
772 stream_get(&src_p.u.prefix, s, src_p.prefixlen);
773 if (src_p.family == AF_INET)
774 {
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);
778 }
779 else
780 {
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);
784 }
785 }
786 #endif /* HAVE_IPV6 */
787
788 len = stream_getc(s);
789 stream_get(if_name, s, len);
790 if_name[len] = '\0';
791
792 ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD,
793 if_name);
794 }
795
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);
799 return 0;
800 }