summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--zebra/ioctl.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 835f1f493..7a3591728 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -179,10 +179,15 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
{
int ret;
struct ifaliasreq addreq;
- struct sockaddr_in addr;
- struct sockaddr_in mask;
+ struct sockaddr_in addr, mask, peer;
struct prefix_ipv4 *p;
+ /* don't configure PtP addresses on broadcast ifs or reverse */
+ if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
+ errno = EINVAL;
+ return -1;
+ }
+
p = (struct prefix_ipv4 *)ifc->address;
rib_lookup_and_pushup(p, ifp->vrf_id);
@@ -197,6 +202,18 @@ int if_set_prefix(struct interface *ifp, struct connected *ifc)
#endif
memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
+ if (CONNECTED_PEER(ifc)) {
+ p = (struct prefix_ipv4 *)ifc->destination;
+ memset(&mask, 0, sizeof(struct sockaddr_in));
+ peer.sin_addr = p->prefix;
+ peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ peer.sin_len = sizeof(struct sockaddr_in);
+#endif
+ memcpy(&addreq.ifra_broadaddr, &peer,
+ sizeof(struct sockaddr_in));
+ }
+
memset(&mask, 0, sizeof(struct sockaddr_in));
masklen2ip(p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;
@@ -217,10 +234,15 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
{
int ret;
struct ifaliasreq addreq;
- struct sockaddr_in addr;
- struct sockaddr_in mask;
+ struct sockaddr_in addr, mask, peer;
struct prefix_ipv4 *p;
+ /* this would probably wreak havoc */
+ if (!(ifp->flags & IFF_POINTOPOINT) != !CONNECTED_PEER(ifc)) {
+ errno = EINVAL;
+ return -1;
+ }
+
p = (struct prefix_ipv4 *)ifc->address;
memset(&addreq, 0, sizeof addreq);
@@ -234,6 +256,18 @@ int if_unset_prefix(struct interface *ifp, struct connected *ifc)
#endif
memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in));
+ if (CONNECTED_PEER(ifc)) {
+ p = (struct prefix_ipv4 *)ifc->destination;
+ memset(&mask, 0, sizeof(struct sockaddr_in));
+ peer.sin_addr = p->prefix;
+ peer.sin_family = p->family;
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ peer.sin_len = sizeof(struct sockaddr_in);
+#endif
+ memcpy(&addreq.ifra_broadaddr, &peer,
+ sizeof(struct sockaddr_in));
+ }
+
memset(&mask, 0, sizeof(struct sockaddr_in));
masklen2ip(p->prefixlen, &mask.sin_addr);
mask.sin_family = p->family;