*/
#include <zebra.h>
+#include <sys/un.h>
#include "prefix.h"
#include "command.h"
#include "buffer.h"
#include "nexthop.h"
#include "vrf.h"
+#include "libfrr.h"
#include "zebra/zserv.h"
#include "zebra/zebra_ns.h"
return zebra_server_send_message(client);
}
+/*
+ * Function used by Zebra to send a PW status update to LDP daemon
+ */
+int zsend_pw_update(struct zserv *client, struct zebra_pw *pw)
+{
+ struct stream *s;
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zserv_create_header(s, ZEBRA_PW_STATUS_UPDATE, pw->vrf_id);
+ stream_write(s, pw->ifname, IF_NAMESIZE);
+ stream_putl(s, pw->ifindex);
+ stream_putl(s, pw->status);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zebra_server_send_message(client);
+}
+
/* Register zebra server interface information. Send current all
interface and address information. */
static int zread_interface_add(struct zserv *client, u_short length,
if (command == ZEBRA_MPLS_LABELS_ADD) {
mpls_lsp_install(zvrf, type, in_label, out_label, gtype, &gate,
ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate,
- ifindex, distance, out_label);
+ mpls_ftn_update(1, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
} else if (command == ZEBRA_MPLS_LABELS_DELETE) {
mpls_lsp_uninstall(zvrf, type, in_label, gtype, &gate, ifindex);
- if (out_label != MPLS_IMP_NULL_LABEL)
- mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate,
- ifindex, distance, out_label);
+ mpls_ftn_update(0, zvrf, type, &prefix, gtype, &gate, ifindex,
+ distance, out_label);
}
}
/* Send response to a label manager connect request to client */
}
}
+static int zread_pseudowire(int command, struct zserv *client, u_short length,
+ vrf_id_t vrf_id)
+{
+ struct stream *s;
+ struct zebra_vrf *zvrf;
+ char ifname[IF_NAMESIZE];
+ ifindex_t ifindex;
+ int type;
+ int af;
+ union g_addr nexthop;
+ uint32_t local_label;
+ uint32_t remote_label;
+ uint8_t flags;
+ union pw_protocol_fields data;
+ uint8_t protocol;
+ struct zebra_pw *pw;
+
+ zvrf = vrf_info_lookup(vrf_id);
+ if (!zvrf)
+ return -1;
+
+ /* Get input stream. */
+ s = client->ibuf;
+
+ /* Get data. */
+ stream_get(ifname, s, IF_NAMESIZE);
+ ifindex = stream_getl(s);
+ type = stream_getl(s);
+ af = stream_getl(s);
+ switch (af) {
+ case AF_INET:
+ nexthop.ipv4.s_addr = stream_get_ipv4(s);
+ break;
+ case AF_INET6:
+ stream_get(&nexthop.ipv6, s, 16);
+ break;
+ default:
+ return -1;
+ }
+ local_label = stream_getl(s);
+ remote_label = stream_getl(s);
+ flags = stream_getc(s);
+ stream_get(&data, s, sizeof(data));
+ protocol = client->proto;
+
+ pw = zebra_pw_find(zvrf, ifname);
+ switch (command) {
+ case ZEBRA_PW_ADD:
+ if (pw) {
+ zlog_warn("%s: pseudowire %s already exists [%s]",
+ __func__, ifname,
+ zserv_command_string(command));
+ return -1;
+ }
+
+ zebra_pw_add(zvrf, ifname, protocol, client);
+ break;
+ case ZEBRA_PW_DELETE:
+ if (!pw) {
+ zlog_warn("%s: pseudowire %s not found [%s]", __func__,
+ ifname, zserv_command_string(command));
+ return -1;
+ }
+
+ zebra_pw_del(zvrf, pw);
+ break;
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ if (!pw) {
+ zlog_warn("%s: pseudowire %s not found [%s]", __func__,
+ ifname, zserv_command_string(command));
+ return -1;
+ }
+
+ switch (command) {
+ case ZEBRA_PW_SET:
+ pw->enabled = 1;
+ break;
+ case ZEBRA_PW_UNSET:
+ pw->enabled = 0;
+ break;
+ }
+
+ zebra_pw_change(pw, ifindex, type, af, &nexthop, local_label,
+ remote_label, flags, &data);
+ break;
+ }
+
+ return 0;
+}
+
/* Cleanup registered nexthops (across VRFs) upon client disconnect. */
static void zebra_client_close_cleanup_rnh(struct zserv *client)
{
zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),
client);
+ /* Remove pseudowires associated with this client */
+ zebra_pw_client_close(client);
+
/* Close file descriptor. */
if (client->sock) {
unsigned long nroutes;
case ZEBRA_INTERFACE_SET_MASTER:
zread_interface_set_master(client, sock, length);
break;
+ case ZEBRA_PW_ADD:
+ case ZEBRA_PW_DELETE:
+ case ZEBRA_PW_SET:
+ case ZEBRA_PW_UNSET:
+ zread_pseudowire(command, client, length, vrf_id);
+ break;
default:
zlog_info("Zebra received unknown command %d", command);
break;
return 0;
}
-#ifdef HAVE_TCP_ZEBRA
-/* Make zebra's server socket. */
-static void zebra_serv()
-{
- int ret;
- int accept_sock;
- struct sockaddr_in addr;
-
- accept_sock = socket(AF_INET, SOCK_STREAM, 0);
-
- if (accept_sock < 0) {
- zlog_warn("Can't create zserv stream socket: %s",
- safe_strerror(errno));
- zlog_warn(
- "zebra can't provice full functionality due to above error");
- return;
- }
-
- memset(&addr, 0, sizeof(struct sockaddr_in));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(ZEBRA_PORT);
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- addr.sin_len = sizeof(struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- sockopt_reuseaddr(accept_sock);
- sockopt_reuseport(accept_sock);
-
- if (zserv_privs.change(ZPRIVS_RAISE))
- zlog_err("Can't raise privileges");
-
- ret = bind(accept_sock, (struct sockaddr *)&addr,
- sizeof(struct sockaddr_in));
- if (ret < 0) {
- zlog_warn("Can't bind to stream socket: %s",
- safe_strerror(errno));
- zlog_warn(
- "zebra can't provice full functionality due to above error");
- close(accept_sock); /* Avoid sd leak. */
- return;
- }
-
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog_err("Can't lower privileges");
-
- ret = listen(accept_sock, 1);
- if (ret < 0) {
- zlog_warn("Can't listen to stream socket: %s",
- safe_strerror(errno));
- zlog_warn(
- "zebra can't provice full functionality due to above error");
- close(accept_sock); /* Avoid sd leak. */
- return;
- }
-
- zebra_event(ZEBRA_SERV, accept_sock, NULL);
-}
-#else /* HAVE_TCP_ZEBRA */
-
-/* For sockaddr_un. */
-#include <sys/un.h>
-
-/* zebra server UNIX domain socket. */
-static void zebra_serv_un(const char *path)
+/* Make zebra server socket, wiping any existing one (see bug #403). */
+void zebra_zserv_socket_init(char *path)
{
int ret;
- int sock, len;
- struct sockaddr_un serv;
+ int sock;
mode_t old_mask;
+ struct sockaddr_storage sa;
+ socklen_t sa_len;
- /* First of all, unlink existing socket */
- unlink(path);
+ if (!frr_zclient_addr(&sa, &sa_len, path))
+ /* should be caught in zebra main() */
+ return;
/* Set umask */
old_mask = umask(0077);
/* Make UNIX domain socket. */
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ sock = socket(sa.ss_family, SOCK_STREAM, 0);
if (sock < 0) {
- zlog_warn("Can't create zserv unix socket: %s",
+ zlog_warn("Can't create zserv socket: %s",
safe_strerror(errno));
zlog_warn(
"zebra can't provide full functionality due to above error");
return;
}
- /* Make server socket. */
- memset(&serv, 0, sizeof(struct sockaddr_un));
- serv.sun_family = AF_UNIX;
- strncpy(serv.sun_path, path, strlen(path));
-#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
- len = serv.sun_len = SUN_LEN(&serv);
-#else
- len = sizeof(serv.sun_family) + strlen(serv.sun_path);
-#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
-
- ret = bind(sock, (struct sockaddr *)&serv, len);
+ if (sa.ss_family != AF_UNIX) {
+ sockopt_reuseaddr(sock);
+ sockopt_reuseport(sock);
+ } else {
+ struct sockaddr_un *suna = (struct sockaddr_un *)&sa;
+ if (suna->sun_path[0])
+ unlink(suna->sun_path);
+ }
+
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog_err("Can't raise privileges");
+
+ ret = bind(sock, (struct sockaddr *)&sa, sa_len);
if (ret < 0) {
- zlog_warn("Can't bind to unix socket %s: %s", path,
+ zlog_warn("Can't bind zserv socket on %s: %s", path,
safe_strerror(errno));
zlog_warn(
"zebra can't provide full functionality due to above error");
close(sock);
return;
}
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog_err("Can't lower privileges");
ret = listen(sock, 5);
if (ret < 0) {
- zlog_warn("Can't listen to unix socket %s: %s", path,
+ zlog_warn("Can't listen to zserv socket %s: %s", path,
safe_strerror(errno));
zlog_warn(
"zebra can't provide full functionality due to above error");
zebra_event(ZEBRA_SERV, sock, NULL);
}
-#endif /* HAVE_TCP_ZEBRA */
static void zebra_event(enum event event, int sock, struct zserv *client)
/* Route-map */
zebra_route_map_init();
}
-
-/* Make zebra server socket, wiping any existing one (see bug #403). */
-void zebra_zserv_socket_init(char *path)
-{
-#ifdef HAVE_TCP_ZEBRA
- zebra_serv();
-#else
- zebra_serv_un(path ? path : ZEBRA_SERV_PATH);
-#endif /* HAVE_TCP_ZEBRA */
-}