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>