]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_network.c
Support for multi-client and client reg msg
[mirror_frr.git] / ospfd / ospf_network.c
index 035993e2f2358b854ddcbc3c9eec7665eadfc67c..2f167a50a5e0fcaf459d675eaf8c00a93dc7b464 100644 (file)
@@ -41,6 +41,7 @@ extern struct zebra_privs_t ospfd_privs;
 #include "ospfd/ospf_lsdb.h"
 #include "ospfd/ospf_neighbor.h"
 #include "ospfd/ospf_packet.h"
+#include "ospfd/ospf_dump.h"
 
 
 
@@ -51,8 +52,8 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
 {
   int ret;
   
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
+                                   htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
@@ -60,8 +61,8 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
               "on # of multicast group memberships has been exceeded?",
                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s join AllSPFRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.",
+              inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -72,16 +73,16 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
+                                   htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
               "ifindex %u, AllSPFRouters): %s",
                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s leave AllSPFRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -93,8 +94,8 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
+                                   htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
@@ -102,8 +103,8 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
               "on # of multicast group memberships has been exceeded?",
                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s join AllDRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] join AllDRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -114,16 +115,16 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
+                                   htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
               "ifindex %u, AllDRouters): %s",
                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s leave AllDRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -150,8 +151,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
     zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
               top->fd, safe_strerror (errno));
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF,
-                                   p->u.prefix4, 0, ifindex);
+  ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
   if (ret < 0)
     zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
              "ifindex %u): %s",
@@ -164,11 +164,10 @@ int
 ospf_sock_init (void)
 {
   int ospf_sock;
-  /*
-   * XXX warning: unused variable `tos'
-   * tos should be ifdefed similarly to usage
-   */
-  int ret, tos, hincl = 1;
+  int ret, hincl = 1;
+  int bufsize = (8 * 1024 * 1024);
+  int optval;
+  socklen_t optlen = sizeof(optval);
 
   if ( ospfd_privs.change (ZPRIVS_RAISE) )
     zlog_err ("ospf_sock_init: could not raise privs, %s",
@@ -177,11 +176,12 @@ ospf_sock_init (void)
   ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
   if (ospf_sock < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    safe_strerror (errno) );
-      zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (errno));
-      exit(-1);
+      zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno));
+      exit(1);
     }
     
 #ifdef IP_HDRINCL
@@ -189,24 +189,25 @@ ospf_sock_init (void)
   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
   if (ret < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    safe_strerror (errno) );
-      zlog_warn ("Can't set IP_HDRINCL option for fd %d",ospf_sock);
+      zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s",
+                ospf_sock, safe_strerror(save_errno));
     }
 #elif defined (IPTOS_PREC_INTERNETCONTROL)
 #warning "IP_HDRINCL not available on this system"
 #warning "using IPTOS_PREC_INTERNETCONTROL"
-  /* Set precedence field. */
-  tos = IPTOS_PREC_INTERNETCONTROL;
-  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_TOS,
-                   (char *) &tos, sizeof (int));
+  ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL);
   if (ret < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    safe_strerror (errno) );
-      zlog_warn ("can't set sockopt IP_TOS %d to socket %d", tos, ospf_sock);
+      zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s",
+                tos, ospf_sock, safe_strerror(save_errno));
       close (ospf_sock);       /* Prevent sd leak. */
       return ret;
     }
@@ -225,6 +226,73 @@ ospf_sock_init (void)
       zlog_err ("ospf_sock_init: could not lower privs, %s",
                safe_strerror (errno) );
     }
+
+  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
+                        &bufsize, sizeof (bufsize))) < 0)
+    {
+      zlog_err ("Couldn't increase raw rbuf size: %s\n", safe_strerror(errno));
+    }
+
+  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
+                        &optval, &optlen)) < 0)
+    {
+      zlog_err("getsockopt of SO_RCVBUF failed with error %s\n", safe_strerror(errno));
+    }
+  if (optval < bufsize)
+    {
+      zlog_err("Unable to SO_RCVBUF to %d, set to %d\n", bufsize, optval);
+    }
+
+
+  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
+                        &bufsize, sizeof (bufsize))) < 0)
+    {
+      zlog_err ("Couldn't increase raw wbuf size: %s\n", safe_strerror(errno));
+    }
+
+  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
+                        &optval, &optlen)) < 0)
+    {
+      zlog_err ("getsockopt of SO_SNDBUF failed with error %s\n", safe_strerror(errno));
+    }
+  if (optval < bufsize)
+    {
+      zlog_err ("Unable to SO_SNDBUF to %d, set to %d\n", bufsize, optval);
+    }
  
   return ospf_sock;
 }
+
+void
+ospf_adjust_sndbuflen (struct ospf * ospf, unsigned int buflen)
+{
+  int ret, newbuflen;
+  /* Check if any work has to be done at all. */
+  if (ospf->maxsndbuflen >= buflen)
+    return;
+  if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
+    zlog_debug ("%s: adjusting OSPF send buffer size to %d",
+      __func__, buflen);
+  if (ospfd_privs.change (ZPRIVS_RAISE))
+    zlog_err ("%s: could not raise privs, %s", __func__,
+      safe_strerror (errno));
+  /* Now we try to set SO_SNDBUF to what our caller has requested
+   * (the MTU of a newly added interface). However, if the OS has
+   * truncated the actual buffer size to somewhat less size, try
+   * to detect it and update our records appropriately. The OS
+   * may allocate more buffer space, than requested, this isn't
+   * a error.
+   */
+  ret = setsockopt_so_sendbuf (ospf->fd, buflen);
+  newbuflen = getsockopt_so_sendbuf (ospf->fd);
+  if (ret < 0 || newbuflen < 0 || newbuflen < (int) buflen)
+    zlog_warn ("%s: tried to set SO_SNDBUF to %u, but got %d",
+      __func__, buflen, newbuflen);
+  if (newbuflen >= 0)
+    ospf->maxsndbuflen = (unsigned int)newbuflen;
+  else
+    zlog_warn ("%s: failed to get SO_SNDBUF", __func__);
+  if (ospfd_privs.change (ZPRIVS_LOWER))
+    zlog_err ("%s: could not lower privs, %s", __func__,
+      safe_strerror (errno));
+}