Annotation of embedaddon/quagga/zebra/irdp_main.c, revision 1.1.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>