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

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,
1.1.1.3 ! misho      51:                           ifindex_t ifindex)
1.1       misho      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,
1.1.1.3 ! misho      72:                            ifindex_t ifindex)
1.1       misho      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
1.1.1.3 ! misho      92: ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex)
1.1       misho      93: {
                     94:   int ret;
                     95: 
                     96:   ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
                     97:                                    htonl (OSPF_ALLDROUTERS),
                     98:                                    ifindex);
                     99:   if (ret < 0)
                    100:     zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
                    101:               "ifindex %u, AllDRouters): %s; perhaps a kernel limit "
                    102:               "on # of multicast group memberships has been exceeded?",
                    103:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    104:   else
                    105:     zlog_debug ("interface %s [%u] join AllDRouters Multicast group.",
                    106:                inet_ntoa (p->u.prefix4), ifindex);
                    107: 
                    108:   return ret;
                    109: }
                    110: 
                    111: int
1.1.1.3 ! misho     112: ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, ifindex_t ifindex)
1.1       misho     113: {
                    114:   int ret;
                    115: 
                    116:   ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
                    117:                                    htonl (OSPF_ALLDROUTERS),
                    118:                                    ifindex);
                    119:   if (ret < 0)
                    120:     zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
                    121:               "ifindex %u, AllDRouters): %s",
                    122:                top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    123:   else
                    124:     zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.",
                    125:                inet_ntoa (p->u.prefix4), ifindex);
                    126: 
                    127:   return ret;
                    128: }
                    129: 
                    130: int
1.1.1.3 ! misho     131: ospf_if_ipmulticast (struct ospf *top, struct prefix *p, ifindex_t ifindex)
1.1       misho     132: {
                    133:   u_char val;
                    134:   int ret, len;
                    135:   
                    136:   val = 0;
                    137:   len = sizeof (val);
                    138:   
                    139:   /* Prevent receiving self-origined multicast packets. */
                    140:   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len);
                    141:   if (ret < 0)
                    142:     zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
                    143:               top->fd, safe_strerror(errno));
                    144:   
                    145:   /* Explicitly set multicast ttl to 1 -- endo. */
                    146:   val = 1;
                    147:   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
                    148:   if (ret < 0)
                    149:     zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
                    150:               top->fd, safe_strerror (errno));
                    151: 
                    152:   ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
                    153:   if (ret < 0)
                    154:     zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
                    155:              "ifindex %u): %s",
                    156:              top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
                    157: 
                    158:   return ret;
                    159: }
                    160: 
                    161: int
                    162: ospf_sock_init (void)
                    163: {
                    164:   int ospf_sock;
                    165:   int ret, hincl = 1;
                    166: 
                    167:   if ( ospfd_privs.change (ZPRIVS_RAISE) )
                    168:     zlog_err ("ospf_sock_init: could not raise privs, %s",
                    169:                safe_strerror (errno) );
                    170:     
                    171:   ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
                    172:   if (ospf_sock < 0)
                    173:     {
                    174:       int save_errno = errno;
                    175:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    176:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    177:                    safe_strerror (errno) );
                    178:       zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno));
                    179:       exit(1);
                    180:     }
                    181:     
                    182: #ifdef IP_HDRINCL
                    183:   /* we will include IP header with packet */
                    184:   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
                    185:   if (ret < 0)
                    186:     {
                    187:       int save_errno = errno;
                    188:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    189:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    190:                    safe_strerror (errno) );
                    191:       zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s",
                    192:                 ospf_sock, safe_strerror(save_errno));
                    193:     }
                    194: #elif defined (IPTOS_PREC_INTERNETCONTROL)
                    195: #warning "IP_HDRINCL not available on this system"
                    196: #warning "using IPTOS_PREC_INTERNETCONTROL"
                    197:   ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL);
                    198:   if (ret < 0)
                    199:     {
                    200:       int save_errno = errno;
                    201:       if ( ospfd_privs.change (ZPRIVS_LOWER) )
                    202:         zlog_err ("ospf_sock_init: could not lower privs, %s",
                    203:                    safe_strerror (errno) );
                    204:       zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s",
                    205:                 tos, ospf_sock, safe_strerror(save_errno));
                    206:       close (ospf_sock);       /* Prevent sd leak. */
                    207:       return ret;
                    208:     }
                    209: #else /* !IPTOS_PREC_INTERNETCONTROL */
                    210: #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL"
                    211:   zlog_warn ("IP_HDRINCL option not available");
                    212: #endif /* IP_HDRINCL */
                    213: 
                    214:   ret = setsockopt_ifindex (AF_INET, ospf_sock, 1);
                    215: 
                    216:   if (ret < 0)
                    217:      zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock);
                    218: 
                    219:   if (ospfd_privs.change (ZPRIVS_LOWER))
                    220:     {
                    221:       zlog_err ("ospf_sock_init: could not lower privs, %s",
                    222:                safe_strerror (errno) );
                    223:     }
                    224:  
                    225:   return ospf_sock;
                    226: }
                    227: 
                    228: void
1.1.1.2   misho     229: ospf_adjust_sndbuflen (struct ospf * ospf, unsigned int buflen)
1.1       misho     230: {
                    231:   int ret, newbuflen;
                    232:   /* Check if any work has to be done at all. */
                    233:   if (ospf->maxsndbuflen >= buflen)
                    234:     return;
                    235:   if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE))
                    236:     zlog_debug ("%s: adjusting OSPF send buffer size to %d",
                    237:       __func__, buflen);
                    238:   if (ospfd_privs.change (ZPRIVS_RAISE))
                    239:     zlog_err ("%s: could not raise privs, %s", __func__,
                    240:       safe_strerror (errno));
                    241:   /* Now we try to set SO_SNDBUF to what our caller has requested
                    242:    * (the MTU of a newly added interface). However, if the OS has
                    243:    * truncated the actual buffer size to somewhat less size, try
                    244:    * to detect it and update our records appropriately. The OS
                    245:    * may allocate more buffer space, than requested, this isn't
                    246:    * a error.
                    247:    */
                    248:   ret = setsockopt_so_sendbuf (ospf->fd, buflen);
                    249:   newbuflen = getsockopt_so_sendbuf (ospf->fd);
1.1.1.2   misho     250:   if (ret < 0 || newbuflen < 0 || newbuflen < (int) buflen)
                    251:     zlog_warn ("%s: tried to set SO_SNDBUF to %u, but got %d",
1.1       misho     252:       __func__, buflen, newbuflen);
                    253:   if (newbuflen >= 0)
1.1.1.2   misho     254:     ospf->maxsndbuflen = (unsigned int)newbuflen;
1.1       misho     255:   else
                    256:     zlog_warn ("%s: failed to get SO_SNDBUF", __func__);
                    257:   if (ospfd_privs.change (ZPRIVS_LOWER))
                    258:     zlog_err ("%s: could not lower privs, %s", __func__,
                    259:       safe_strerror (errno));
                    260: }

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