Annotation of embedaddon/quagga/zebra/irdp_main.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *
        !             3:  * Copyright (C) 2000  Robert Olsson.
        !             4:  * Swedish University of Agricultural Sciences
        !             5:  *
        !             6:  * This file is part of GNU Zebra.
        !             7:  *
        !             8:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2, or (at your option) any
        !            11:  * later version.
        !            12:  *
        !            13:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            16:  * General Public License for more details.
        !            17:  *
        !            18:  * You should have received a copy of the GNU General Public License
        !            19:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            20:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            21:  * 02111-1307, USA.  
        !            22:  */
        !            23: 
        !            24: /* 
        !            25:  * This work includes work with the following copywrite:
        !            26:  *
        !            27:  * Copyright (C) 1997, 2000 Kunihiro Ishiguro
        !            28:  *
        !            29:  */
        !            30: 
        !            31: /* 
        !            32:  * Thanks to Jens Låås at Swedish University of Agricultural Sciences
        !            33:  * for reviewing and tests.
        !            34:  */
        !            35: 
        !            36: 
        !            37: #include <zebra.h>
        !            38: 
        !            39: #ifdef HAVE_IRDP
        !            40: 
        !            41: #include "if.h"
        !            42: #include "vty.h"
        !            43: #include "sockunion.h"
        !            44: #include "sockopt.h"
        !            45: #include "prefix.h"
        !            46: #include "command.h"
        !            47: #include "memory.h"
        !            48: #include "stream.h"
        !            49: #include "ioctl.h"
        !            50: #include "connected.h"
        !            51: #include "log.h"
        !            52: #include "zclient.h"
        !            53: #include "thread.h"
        !            54: #include "privs.h"
        !            55: #include "zebra/interface.h"
        !            56: #include "zebra/rtadv.h"
        !            57: #include "zebra/rib.h"
        !            58: #include "zebra/zserv.h"
        !            59: #include "zebra/redistribute.h"
        !            60: #include "zebra/irdp.h"
        !            61: #include <netinet/ip_icmp.h>
        !            62: 
        !            63: #include "checksum.h"
        !            64: #include "if.h"
        !            65: #include "sockunion.h"
        !            66: #include "log.h"
        !            67: 
        !            68: /* GLOBAL VARS */
        !            69: 
        !            70: extern struct zebra_privs_t zserv_privs;
        !            71: 
        !            72: /* Master of threads. */
        !            73: extern struct zebra_t zebrad;
        !            74: struct thread *t_irdp_raw;
        !            75: 
        !            76: /* Timer interval of irdp. */
        !            77: int irdp_timer_interval = IRDP_DEFAULT_INTERVAL;
        !            78: 
        !            79: int
        !            80: irdp_sock_init (void)
        !            81: {
        !            82:   int ret, i;
        !            83:   int save_errno;
        !            84:   int sock;
        !            85: 
        !            86:   if ( zserv_privs.change (ZPRIVS_RAISE) )
        !            87:        zlog_err ("irdp_sock_init: could not raise privs, %s",
        !            88:                   safe_strerror (errno) );
        !            89: 
        !            90:   sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
        !            91:   save_errno = errno;
        !            92: 
        !            93:   if ( zserv_privs.change (ZPRIVS_LOWER) )
        !            94:        zlog_err ("irdp_sock_init: could not lower privs, %s",
        !            95:              safe_strerror (errno) );
        !            96: 
        !            97:   if (sock < 0) {
        !            98:     zlog_warn ("IRDP: can't create irdp socket %s", safe_strerror(save_errno));
        !            99:     return sock;
        !           100:   };
        !           101:   
        !           102:   i = 1;
        !           103:   ret = setsockopt (sock, IPPROTO_IP, IP_TTL, 
        !           104:                         (void *) &i, sizeof (i));
        !           105:   if (ret < 0) {
        !           106:     zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno));
        !           107:     close(sock);
        !           108:     return ret;
        !           109:   };
        !           110:   
        !           111:   ret = setsockopt_ifindex (AF_INET, sock, 1);
        !           112:   if (ret < 0) {
        !           113:     zlog_warn ("IRDP: can't do irdp sockopt %s", safe_strerror(errno));
        !           114:     close(sock);
        !           115:     return ret;
        !           116:   };
        !           117: 
        !           118:   t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, sock); 
        !           119: 
        !           120:   return sock;
        !           121: }
        !           122: 
        !           123: 
        !           124: static int
        !           125: get_pref(struct irdp_interface *irdp, struct prefix *p)
        !           126: {
        !           127:   struct listnode *node;
        !           128:   struct Adv *adv;
        !           129: 
        !           130:   /* Use default preference or use the override pref */
        !           131:   
        !           132:   if( irdp->AdvPrefList == NULL )
        !           133:     return irdp->Preference;
        !           134:   
        !           135:   for (ALL_LIST_ELEMENTS_RO (irdp->AdvPrefList, node, adv))
        !           136:     if( p->u.prefix4.s_addr == adv->ip.s_addr )
        !           137:       return adv->pref;
        !           138: 
        !           139:   return irdp->Preference;
        !           140: }
        !           141: 
        !           142: /* Make ICMP Router Advertisement Message. */
        !           143: static int
        !           144: make_advertisement_packet (struct interface *ifp, 
        !           145:                           struct prefix *p,
        !           146:                           struct stream *s)
        !           147: {
        !           148:   struct zebra_if *zi=ifp->info;
        !           149:   struct irdp_interface *irdp=&zi->irdp;
        !           150:   int size;
        !           151:   int pref;
        !           152:   u_int16_t checksum;
        !           153: 
        !           154:   pref =  get_pref(irdp, p);
        !           155: 
        !           156:   stream_putc (s, ICMP_ROUTERADVERT); /* Type. */
        !           157:   stream_putc (s, 0);          /* Code. */
        !           158:   stream_putw (s, 0);          /* Checksum. */
        !           159:   stream_putc (s, 1);          /* Num address. */
        !           160:   stream_putc (s, 2);          /* Address Entry Size. */
        !           161: 
        !           162:   if(irdp->flags & IF_SHUTDOWN)  
        !           163:     stream_putw (s, 0);
        !           164:   else 
        !           165:     stream_putw (s, irdp->Lifetime);
        !           166: 
        !           167:   stream_putl (s, htonl(p->u.prefix4.s_addr)); /* Router address. */
        !           168:   stream_putl (s, pref);
        !           169: 
        !           170:   /* in_cksum return network byte order value */
        !           171:   size = 16;
        !           172:   checksum = in_cksum (s->data, size);
        !           173:   stream_putw_at (s, 2, htons(checksum));
        !           174: 
        !           175:   return size;
        !           176: }
        !           177: 
        !           178: static void
        !           179: irdp_send(struct interface *ifp, struct prefix *p, struct stream *s)
        !           180: {
        !           181:   struct zebra_if *zi=ifp->info;
        !           182:   struct irdp_interface *irdp=&zi->irdp;
        !           183:   u_int32_t dst;
        !           184:   u_int32_t ttl=1;
        !           185: 
        !           186:   if (! (ifp->flags & IFF_UP)) return; 
        !           187: 
        !           188:   if (irdp->flags & IF_BROADCAST) 
        !           189:     dst =INADDR_BROADCAST ;
        !           190:   else 
        !           191:     dst = htonl(INADDR_ALLHOSTS_GROUP);
        !           192: 
        !           193:   if(irdp->flags & IF_DEBUG_MESSAGES) 
        !           194:     zlog_debug("IRDP: TX Advert on %s %s/%d Holdtime=%d Preference=%d", 
        !           195:              ifp->name,
        !           196:              inet_ntoa(p->u.prefix4), 
        !           197:              p->prefixlen,
        !           198:              irdp->flags & IF_SHUTDOWN? 0 : irdp->Lifetime,
        !           199:              get_pref(irdp, p));
        !           200: 
        !           201:   send_packet (ifp, s, dst, p, ttl);
        !           202: }
        !           203: 
        !           204: static void irdp_advertisement (struct interface *ifp, struct prefix *p)
        !           205: {
        !           206:   struct stream *s;
        !           207:   s = stream_new (128);
        !           208:   make_advertisement_packet (ifp, p, s);
        !           209:   irdp_send(ifp, p, s);
        !           210:   stream_free (s);
        !           211: }
        !           212: 
        !           213: int irdp_send_thread(struct thread *t_advert)
        !           214: {
        !           215:   u_int32_t timer, tmp;
        !           216:   struct interface *ifp = THREAD_ARG (t_advert);
        !           217:   struct zebra_if *zi=ifp->info;
        !           218:   struct irdp_interface *irdp=&zi->irdp;
        !           219:   struct prefix *p;
        !           220:   struct listnode *node, *nnode;
        !           221:   struct connected *ifc;
        !           222: 
        !           223:   irdp->flags &= ~IF_SOLICIT;
        !           224: 
        !           225:   if(ifp->connected) 
        !           226:     for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
        !           227:       {
        !           228:         p = ifc->address;
        !           229:         
        !           230:         if (p->family != AF_INET)
        !           231:           continue;
        !           232:         
        !           233:         irdp_advertisement(ifp, p);
        !           234:         irdp->irdp_sent++;
        !           235:       }
        !           236: 
        !           237:   tmp = irdp->MaxAdvertInterval-irdp->MinAdvertInterval;
        !           238:   timer =  (random () % tmp ) + 1;
        !           239:   timer = irdp->MinAdvertInterval + timer;
        !           240: 
        !           241:   if(irdp->irdp_sent <  MAX_INITIAL_ADVERTISEMENTS &&
        !           242:      timer > MAX_INITIAL_ADVERT_INTERVAL ) 
        !           243:          timer= MAX_INITIAL_ADVERT_INTERVAL;
        !           244: 
        !           245:   if(irdp->flags & IF_DEBUG_MISC)
        !           246:     zlog_debug("IRDP: New timer for %s set to %u\n", ifp->name, timer);
        !           247: 
        !           248:   irdp->t_advertise = thread_add_timer(zebrad.master, irdp_send_thread, ifp, timer);
        !           249:   return 0;
        !           250: }
        !           251: 
        !           252: void irdp_advert_off(struct interface *ifp)
        !           253: {
        !           254:   struct zebra_if *zi=ifp->info;
        !           255:   struct irdp_interface *irdp=&zi->irdp;
        !           256:   struct listnode *node, *nnode;
        !           257:   int i;
        !           258:   struct connected *ifc;
        !           259:   struct prefix *p;
        !           260: 
        !           261:   if(irdp->t_advertise)  thread_cancel(irdp->t_advertise);
        !           262:   irdp->t_advertise = NULL;
        !           263:   
        !           264:   if(ifp->connected) 
        !           265:     for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, ifc))
        !           266:       {
        !           267:         p = ifc->address;
        !           268: 
        !           269:         /* Output some packets with Lifetime 0 
        !           270:            we should add a wait...
        !           271:         */
        !           272: 
        !           273:         for(i=0; i< IRDP_LAST_ADVERT_MESSAGES; i++) 
        !           274:           {
        !           275:             irdp->irdp_sent++;
        !           276:             irdp_advertisement(ifp, p);
        !           277:           }
        !           278:       }
        !           279: }
        !           280: 
        !           281: 
        !           282: void process_solicit (struct interface *ifp)
        !           283: {
        !           284:   struct zebra_if *zi=ifp->info;
        !           285:   struct irdp_interface *irdp=&zi->irdp;
        !           286:   u_int32_t timer;
        !           287: 
        !           288:   /* When SOLICIT is active we reject further incoming solicits 
        !           289:      this keeps down the answering rate so we don't have think
        !           290:      about DoS attacks here. */
        !           291: 
        !           292:   if( irdp->flags & IF_SOLICIT) return;
        !           293: 
        !           294:   irdp->flags |= IF_SOLICIT;
        !           295:   if(irdp->t_advertise)  thread_cancel(irdp->t_advertise);
        !           296:   irdp->t_advertise = NULL;
        !           297: 
        !           298:   timer =  (random () % MAX_RESPONSE_DELAY) + 1;
        !           299: 
        !           300:   irdp->t_advertise = thread_add_timer(zebrad.master, 
        !           301:                                       irdp_send_thread, 
        !           302:                                       ifp, 
        !           303:                                       timer);
        !           304: }
        !           305: 
        !           306: void irdp_finish()
        !           307: {
        !           308: 
        !           309:   struct listnode *node, *nnode;
        !           310:   struct interface *ifp;
        !           311:   struct zebra_if *zi;
        !           312:   struct irdp_interface *irdp;
        !           313: 
        !           314:   zlog_info("IRDP: Received shutdown notification.");
        !           315:   
        !           316:   for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
        !           317:     {
        !           318:       zi = ifp->info;
        !           319:       
        !           320:       if (!zi) 
        !           321:         continue;
        !           322:       irdp = &zi->irdp;
        !           323:       if (!irdp) 
        !           324:         continue;
        !           325: 
        !           326:       if (irdp->flags & IF_ACTIVE ) 
        !           327:         {
        !           328:          irdp->flags |= IF_SHUTDOWN;
        !           329:          irdp_advert_off(ifp);
        !           330:         }
        !           331:     }
        !           332: }
        !           333: 
        !           334: #endif /* HAVE_IRDP */

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