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"
32 #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
33 #define ZEBRA_PTM_RECONNECT_TIME_MAX 300
34 extern struct zebra_t zebrad
;
37 int zebra_ptm_sock
= -1;
38 struct thread
*zebra_ptm_thread
= NULL
;
40 static int zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
42 static void zebra_ptm_finish(void);
43 static int zebra_ptm_socket_init(void);
44 static void zebra_ptm_process_msg(char *msg
);
45 int zebra_ptm_sock_read(struct thread
*);
46 static void zebra_ptm_install_commands (void);
48 const char ZEBRA_PTM_SOCK_NAME
[] = "\0/var/run/ptmd.socket";
50 typedef enum ptm_msg_type
{
59 zebra_ptm_install_commands();
63 zebra_ptm_connect (struct thread
*t
)
65 zebra_ptm_socket_init();
67 if (zebra_ptm_sock
!= -1) {
68 zebra_ptm_thread
= thread_add_read (zebrad
.master
, zebra_ptm_sock_read
, NULL
, zebra_ptm_sock
);
69 zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_INITIAL
;
71 zlog_err("%s: Socket connect to %s failed with err = %d\n", __func__
,
72 ZEBRA_PTM_SOCK_NAME
, errno
);
73 zebra_ptm_reconnect_time
*= 2;
74 if (zebra_ptm_reconnect_time
> ZEBRA_PTM_RECONNECT_TIME_MAX
)
75 zebra_ptm_reconnect_time
= ZEBRA_PTM_RECONNECT_TIME_MAX
;
77 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
, NULL
,
78 zebra_ptm_reconnect_time
);
85 zebra_ptm_finish (void)
87 if (zebra_ptm_sock
!= -1)
89 if (zebra_ptm_thread
!= NULL
)
91 thread_cancel(zebra_ptm_thread
);
92 zebra_ptm_thread
= NULL
;
94 close (zebra_ptm_sock
);
99 DEFUN (zebra_ptm_enable
,
100 zebra_ptm_enable_cmd
,
102 "Enable neighbor check with specified topology\n")
105 struct interface
*ifp
;
109 for (ALL_LIST_ELEMENTS_RO (iflist
, i
, ifp
))
110 if (!ifp
->ptm_enable
)
113 ifp
->ptm_status
= 1; /* to bring down ports that may fail check */
116 zebra_ptm_connect(NULL
);
121 DEFUN (no_zebra_ptm_enable
,
122 no_zebra_ptm_enable_cmd
,
125 "Enable neighbor check with specified topology\n")
128 struct interface
*ifp
;
132 for (ALL_LIST_ELEMENTS_RO (iflist
, i
, ifp
))
136 if (!if_is_operative(ifp
))
140 if (if_is_operative (ifp
) && send_linkup
) {
141 zlog_debug ("%s: Bringing up interface %s\n", __func__
,
153 zebra_ptm_write (struct vty
*vty
)
156 vty_out (vty
, "ptm-enable%s", VTY_NEWLINE
);
162 zebra_ptm_socket_init (void)
166 struct sockaddr_un addr
;
169 sock
= socket (PF_UNIX
, SOCK_STREAM
, 0);
173 /* Make server socket. */
174 memset (&addr
, 0, sizeof (struct sockaddr_un
));
175 addr
.sun_family
= AF_UNIX
;
176 memcpy (&addr
.sun_path
, ZEBRA_PTM_SOCK_NAME
,
177 sizeof(ZEBRA_PTM_SOCK_NAME
));
179 ret
= connect(sock
, (struct sockaddr
*) &addr
,
180 sizeof (addr
.sun_family
)+sizeof (ZEBRA_PTM_SOCK_NAME
)-1);
183 zlog_err("%s: Unable to connect to socket %s, errno=%d\n",
184 __func__
, ZEBRA_PTM_SOCK_NAME
, errno
);
188 zlog_debug ("%s: connection to ptm socket %s succeeded\n",
189 __func__
, ZEBRA_PTM_SOCK_NAME
);
190 zebra_ptm_sock
= sock
;
195 zebra_ptm_install_commands (void)
197 install_element (CONFIG_NODE
, &zebra_ptm_enable_cmd
);
198 install_element (CONFIG_NODE
, &no_zebra_ptm_enable_cmd
);
202 zebra_ptm_process_msg (char *buf
)
204 char port_name
[IF_NAMESIZE
+1];
209 struct interface
*ifp
;
210 int scan_count
, bytes_read
;
212 const char *delim
= "\n";
213 struct in_addr dest_addr
;
214 struct prefix dest_prefix
;
217 /* the messages from the ptm ctl socket are in text only */
218 /* with a fixed format:<count> <portname> <type> <pass|fail> */
219 pos
= strtok(buf
, delim
);
220 while (pos
!= NULL
) {
221 if (strstr(pos
, "EOF") != NULL
)
223 scan_count
= sscanf(pos
, "%3s %16s %1s %4s %n", byte_len
, port_name
, type
, status
, &bytes_read
);
225 if (scan_count
== 4) {
227 zlog_debug("%s: %s received new status %s, type %s with scan count = %d\n",
228 __func__
, port_name
, type
, status
, scan_count
);
230 ifp
= if_lookup_by_name(port_name
);
232 zlog_err("%s: %s not found in interface list\n", __func__
, port_name
);
236 if (strchr(type
, "B") == 0) {
238 pos
= pos
+ bytes_read
;
239 scan_count
= sscanf(pos
, "%11s", tgt_ip
);
244 if (strcmp(status
, "pass") == 0) {
245 if (!ifp
->ptm_status
) {
247 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
))
250 } else if (strcmp (status
, "fail") == 0) {
251 if (ifp
->ptm_status
) {
253 if (ifp
->ptm_enable
&& if_is_no_ptm_operative (ifp
)) {
254 if (msg_type
== PTM_BFD
) {
256 if (inet_pton(AF_INET
, tgt_ip
, &dest_addr
) <= 0) {
257 zlog_err ("%s: Not a valid destination address: %s",
261 dest_prefix
.family
= AF_INET
;
262 dest_prefix
.u
.prefix4
= dest_addr
;
263 dest_prefix
.prefixlen
= IPV4_MAX_PREFIXLEN
;
265 /* Send BFD message with ifp and dest_prefix to protocols */
273 pos
= strtok(NULL
, delim
);
278 zebra_ptm_sock_read (struct thread
*thread
)
281 char rcvbuf
[ZEBRA_PTM_MAX_SOCKBUF
];
284 sock
= THREAD_FD (thread
);
289 nbytes
= recv(sock
, rcvbuf
, sizeof(rcvbuf
), 0);
293 if (nbytes
< 0 && errno
!= EWOULDBLOCK
&& errno
!= EAGAIN
)
294 zlog_warn ("routing socket error: %s", safe_strerror (errno
));
297 zebra_ptm_thread
= thread_add_timer (zebrad
.master
, zebra_ptm_connect
, NULL
,
298 zebra_ptm_reconnect_time
);
302 zlog_debug ("%s: Received message \n%s\n", __func__
, rcvbuf
);
303 zebra_ptm_thread
= thread_add_read (zebrad
.master
, zebra_ptm_sock_read
, NULL
, sock
);
305 zebra_ptm_process_msg (rcvbuf
);