summaryrefslogtreecommitdiff
path: root/zebra/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/ioctl.c')
-rw-r--r--zebra/ioctl.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 835f1f4934..58118ce006 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -44,7 +44,7 @@ extern struct zebra_privs_t zserv_privs;
/* clear and set interface name string */
void ifreq_set_name(struct ifreq *ifreq, struct interface *ifp)
{
- strncpy(ifreq->ifr_name, ifp->name, IFNAMSIZ);
+ strlcpy(ifreq->ifr_name, ifp->name, sizeof(ifreq->ifr_name));
}
/* call ioctl system call */
@@ -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;