Annotation of embedaddon/quagga/ospfd/ospf_network.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * OSPF network related functions
                      3:  *   Copyright (C) 1999 Toshiaki Takada
                      4:  *
                      5:  * This file is part of GNU Zebra.
                      6:  *
                      7:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2, or (at your option) any
                     10:  * later version.
                     11:  *
                     12:  * GNU Zebra is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License
                     18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     20:  * 02111-1307, USA.
                     21:  */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "thread.h"
                     26: #include "linklist.h"
                     27: #include "prefix.h"
                     28: #include "if.h"
                     29: #include "sockunion.h"
                     30: #include "log.h"
                     31: #include "sockopt.h"
                     32: #include "privs.h"
                     33: 
                     34: extern struct zebra_privs_t ospfd_privs;
                     35: 
                     36: #include "ospfd/ospfd.h"
                     37: #include "ospfd/ospf_network.h"
                     38: #include "ospfd/ospf_interface.h"
                     39: #include "ospfd/ospf_asbr.h"
                     40: #include "ospfd/ospf_lsa.h"
                     41: #include "ospfd/ospf_lsdb.h"
                     42: #include "ospfd/ospf_neighbor.h"
                     43: #include "ospfd/ospf_packet.h"
                     44: #include "ospfd/ospf_dump.h"
                     45: 
                     46: 
                     47: 
                     48: /* Join to the OSPF ALL SPF ROUTERS multicast group. */
                     49: int
                     50: ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
                     51:                           unsigned int ifindex)
                     52: {
                     53:   int ret;
                     54:   
                     55:   ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
                     56:                                    htonl (OSPF_ALLSPFROUTERS),
                     57:                                    ifindex);
                     58:   if (ret < 0)
                     59:     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
                     60:               "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit "
                     61:               "on # of multicast group memberships has been exceeded?",
                     62:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                     63:   else
                     64:     zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.",
                     65:               inet_ntoa (p->u.prefix4), ifindex);
                     66: 
                     67:   return ret;
                     68: }
                     69: 
                     70: int
                     71: ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
                     72:                            unsigned int ifindex)
                     73: {
                     74:   int ret;
                     75: 
                     76:   ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
                     77:                                    htonl (OSPF_ALLSPFROUTERS),
                     78:                                    ifindex);
                     79:   if (ret < 0)
                     80:     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
                     81:               "ifindex %u, AllSPFRouters): %s",
                     82:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                     83:   else
                     84:     zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.",
                     85:                inet_ntoa (p->u.prefix4), ifindex);
                     86: 
                     87:   return ret;
                     88: }
                     89: 
                     90: /* Join to the OSPF ALL Designated ROUTERS multicast group. */
                     91: int
                     92: ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
                     93:                         ifindex)
                     94: {
                     95:   int ret;
                     96: 
                     97:   ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
                     98:                                    htonl (OSPF_ALLDROUTERS),
                     99:                                    ifindex);
                    100:   if (ret < 0)
                    101:     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
                    102:               "ifindex %u, AllDRouters): %s; perhaps a kernel limit "
                    103:               "on # of multicast group memberships has been exceeded?",
                    104:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    105:   else
                    106:     zlog_debug ("interface %s [%u] join AllDRouters Multicast group.",
                    107:                inet_ntoa (p->u.prefix4), ifindex);
                    108: 
                    109:   return ret;
                    110: }
                    111: 
                    112: int
                    113: ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
                    114:                          ifindex)
                    115: {
                    116:   int ret;
                    117: 
                    118:   ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
                    119:                                    htonl (OSPF_ALLDROUTERS),
                    120:                                    ifindex);
                    121:   if (ret < 0)
                    122:     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
                    123:               "ifindex %u, AllDRouters): %s",
                    124:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    125:   else
                    126:     zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.",
                    127:                inet_ntoa (p->u.prefix4), ifindex);
                    128: 
                    129:   return ret;
                    130: }
                    131: 
                    132: int
                    133: ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
                    134: {
                    135:   u_char val;
                    136:   int ret, len;
                    137:   
                    138:   val = 0;
                    139:   len = sizeof (val);
                    140:   
                    141:   /* Prevent receiving self-origined multicast packets. */
                    142:   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len);
                    143:   if (ret < 0)
                    144:     zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
                    145:               top->fd, safe_strerror(errno));
                    146:   
                    147:   /* Explicitly set multicast ttl to 1 -- endo. */
                    148:   val = 1;
                    149:   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
                    150:   if (ret < 0)
                    151:     zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
                    152:               top->fd, safe_strerror (errno));
                    153: 
                    154:   ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
                    155:   if (ret < 0)
                    156:     zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
                    157:              "ifindex %u): %s",
                    158:              top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    159: 
                    160:   return ret;
                    161: }
                    162: 
                    163: int
                    164: ospf_sock_init (void)
                    165: {
                    166:   int ospf_sock;
                    167:   int ret, hincl = 1;
                    168: 
                    169:   if ( ospfd_privs.change (ZPRIVS_RAISE) )
                    170:     zlog_err ("ospf_sock_init: could not raise privs, %s",
                    171:                safe_strerror (errno) );
                    172:     
                    173:   ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
                    174:   if (ospf_sock < 0)
                    175:     {
                    176:       int save_errno = errno;
                    177:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    178:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    179:                    safe_strerror (errno) );
                    180:       zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno));
                    181:       exit(1);
                    182:     }
                    183:     
                    184: #ifdef IP_HDRINCL
                    185:   /* we will include IP header with packet */
                    186:   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
                    187:   if (ret < 0)
                    188:     {
                    189:       int save_errno = errno;
                    190:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    191:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    192:                    safe_strerror (errno) );
                    193:       zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s",
                    194:                 ospf_sock, safe_strerror(save_errno));
                    195:     }
                    196: #elif defined (IPTOS_PREC_INTERNETCONTROL)
                    197: #warning "IP_HDRINCL not available on this system"
                    198: #warning "using IPTOS_PREC_INTERNETCONTROL"
                    199:   ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL);
                    200:   if (ret < 0)
                    201:     {
                    202:       int save_errno = errno;
                    203:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    204:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    205:                    safe_strerror (errno) );
                    206:       zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s",
                    207:                 tos, ospf_sock, safe_strerror(save_errno));
                    208:       close (ospf_sock);       /* Prevent sd leak. */
                    209:       return ret;
                    210:     }
                    211: #else /* !IPTOS_PREC_INTERNETCONTROL */
                    212: #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
                    213:   zlog_warn ("IP_HDRINCL option not available");
                    214: #endif /* IP_HDRINCL */
                    215: 
                    216:   ret = setsockopt_ifindex (AF_INET, ospf_sock, 1);
                    217: 
                    218:   if (ret < 0)
                    219:      zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock);
                    220: 
                    221:   if (ospfd_privs.change (ZPRIVS_LOWER))
                    222:     {
                    223:       zlog_err ("ospf_sock_init: could not lower privs, %s",
                    224:                safe_strerror (errno) );
                    225:     }
                    226:  
                    227:   return ospf_sock;
                    228: }
                    229: 
                    230: void
1.1.1.2 ! misho     231: ospf_adjust_sndbuflen (struct ospf * ospf, unsigned int buflen)
1.1       misho     232: {
                    233:   int ret, newbuflen;
                    234:   /* Check if any work has to be done at all. */
                    235:   if (ospf->maxsndbuflen >= buflen)
                    236:     return;
                    237:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    238:     zlog_debug ("%s: adjusting OSPF send buffer size to %d",
                    239:       __func__, buflen);
                    240:   if (ospfd_privs.change (ZPRIVS_RAISE))
                    241:     zlog_err ("%s: could not raise privs, %s", __func__,
                    242:       safe_strerror (errno));
                    243:   /* Now we try to set SO_SNDBUF to what our caller has requested
                    244:    * (the MTU of a newly added interface). However, if the OS has
                    245:    * truncated the actual buffer size to somewhat less size, try
                    246:    * to detect it and update our records appropriately. The OS
                    247:    * may allocate more buffer space, than requested, this isn't
                    248:    * a error.
                    249:    */
                    250:   ret = setsockopt_so_sendbuf (ospf->fd, buflen);
                    251:   newbuflen = getsockopt_so_sendbuf (ospf->fd);
1.1.1.2 ! misho     252:   if (ret < 0 || newbuflen < 0 || newbuflen < (int) buflen)
        !           253:     zlog_warn ("%s: tried to set SO_SNDBUF to %u, but got %d",
1.1       misho     254:       __func__, buflen, newbuflen);
                    255:   if (newbuflen >= 0)
1.1.1.2 ! misho     256:     ospf->maxsndbuflen = (unsigned int)newbuflen;
1.1       misho     257:   else
                    258:     zlog_warn ("%s: failed to get SO_SNDBUF", __func__);
                    259:   if (ospfd_privs.change (ZPRIVS_LOWER))
                    260:     zlog_err ("%s: could not lower privs, %s", __func__,
                    261:       safe_strerror (errno));
                    262: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>