summaryrefslogtreecommitdiffstats
path: root/zebra/ioctl.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2010-02-03 07:36:04 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2017-08-27 23:40:34 +0200
commit5a41e961f8460f4c2126ac3a393e6a73bbe56035 (patch)
treeaf07f194e17be6c5b2c2d4fd9cad8412cf2c8959 /zebra/ioctl.c
parentzebra: add '[no] ip address A.B.C.D peer A.B.C.D/M' (diff)
downloadfrr-5a41e961f8460f4c2126ac3a393e6a73bbe56035.tar.xz
frr-5a41e961f8460f4c2126ac3a393e6a73bbe56035.zip
zebra: configure PtP address on ifaliasreq systems
support configuring a point-to-point address on systems using ioctl / struct ifaliasreq. error out when interface/address type mismatch. tested on FreeBSD 8.0-RELEASE. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'zebra/ioctl.c')
-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;