1 /* ICMP Router Discovery Messages
2 * Copyright (C) 1997, 2000 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 #include <netinet/ip_icmp.h>
31 #include "sockunion.h"
34 #include "zebra/irdp.h"
36 /* Default does nothing. */
37 int irdp_mode = IRDP_NONE;
39 /* Timer interval of irdp. */
40 int irdp_timer_interval = IRDP_DEFAULT_INTERVAL;
42 /* Max solicitations */
43 int max_solicitations = MAX_SOLICITATIONS;
45 #define IRDP_SOLICIT_PACKET_SIZE 8
47 static struct irdp *irdp_head = NULL;
49 extern int in_cksum (void *ptr, int nbytes);
51 char *icmp_type_str[] =
63 "Router Solicitation",
77 if (type < 0 || type >= (sizeof icmp_type_str / sizeof (char *))) {
78 return "OUT-OF-RANGE";
80 return icmp_type_str [type];
92 irdp_delete_interface ()
100 struct irdp *new = XMALLOC (0, sizeof (struct irdp));
101 memset (new, 0, sizeof (struct irdp));
106 irdp_route_free (struct irdp *route)
124 route_add (struct in_addr addr, unsigned long pref)
126 struct irdp *new = irdp_route_new();
131 printf ("address %s\n", inet_ntoa (new->prefix));
132 printf ("pref %ld\n", new->pref);
140 for (p = irdp_head; p != NULL; p = p->next) {
141 if (p->timer < time) {
149 #define FLAG_TEST(a) ((ifp->flags & (a)) == (a))
152 send_multicast (struct interface *ifp, int sock, struct stream *s, int size)
154 struct sockaddr_in sin;
157 struct connected *connected;
160 for (node = listhead (ifp->connected); node; nextnode (node))
162 connected = getdata (node);
165 if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,
166 addr, 0, ifp->ifindex) < 0)
168 perror ("setsockopt");
172 sin.sin_addr.s_addr = htonl (INADDR_ALLRTRS_GROUP);
173 sin.sin_family = AF_INET;
175 nbytes = sendto (sock, s->data, size, 0,
176 (struct sockaddr *) &sin, sizeof (struct sockaddr));
188 struct sockaddr_in sin;
190 printf ("broadcast\n");
191 inet_aton ("255.255.255.255", &sin.sin_addr);
195 irdp_send_solicit (int sock, struct stream *s, int size)
197 struct interface *ifp;
200 for (node = listhead (iflist); node; nextnode (node))
202 ifp = getdata (node);
203 if (FLAG_TEST (IFF_UP | IFF_MULTICAST))
205 send_multicast (ifp, sock, s, size);
207 else if (FLAG_TEST (IFF_UP | IFF_BROADCAST))
215 ipv4_multicast_join (int sock,
216 struct in_addr group,
218 unsigned int ifindex)
222 ret = setsockopt_multicast_ipv4 (sock, IP_ADD_MEMBERSHIP,
223 ifa, group.saddr, ifindex);
226 zlog (NULL, LOG_INFO, "can't setsockopt IP_ADD_MEMBERSHIP");
231 /* multicast packet recieve socket */
233 irdp_multicast_socket (int sock, struct in_addr group)
235 struct interface *ifp;
239 for (node = listhead (iflist); node; nextnode (node))
241 ifp = getdata (node);
243 if ((ifp->flags & IFF_UP) && (ifp->flags & IFF_MULTICAST))
245 ipv4_multicast_join (sock, group, addr, ifp->ifindex);
264 struct in_addr irdp_group;
269 irdp_group.s_addr = htonl (INADDR_ALLHOSTS_GROUP);
272 irdp_group.s_addr = htonl (INADDR_ALLRTRS_GROUP);
278 irdp_multicast_socket (sock, irdp_group);
281 /* Make ICMP Router Solicitation Message. */
283 make_solicit_packet (struct stream *s)
288 stream_putc (s, ICMP_ROUTERSOLICIT); /* Type. */
289 stream_putc (s, 0); /* Code. */
290 stream_putw (s, 0); /* Checksum. */
291 stream_putl (s, 0); /* Reserved. */
293 /* in_cksum return network byte order value */
294 size = IRDP_SOLICIT_PACKET_SIZE;
295 checksum = in_cksum (s->data, size);
296 stream_putw_at (s, checksum, 2);
298 return IRDP_SOLICIT_PACKET_SIZE;
302 irdp_solicit (int sock)
306 s = stream_new (IRDP_SOLICIT_PACKET_SIZE);
307 make_solicit_packet (s);
308 irdp_send_solicit (sock, s, IRDP_SOLICIT_PACKET_SIZE);
311 #define ICMP_MINLEN 8
313 /* check validity of the packet */
315 irdp_valid_check (char *packet, size_t size, struct sockaddr_in *from)
319 icmp = (struct icmp *) packet;
321 if (in_cksum (packet, size)) {
322 zlog_warn ("ICMP %s packet from %s: Bad checksum, silently ignored",
323 icmp_type (icmp->icmp_type),
324 inet_ntoa (from->sin_addr));
328 if (icmp->icmp_code != 0) {
329 zlog_warn ("ICMP %s packet from %s: Bad ICMP type code, silently ignored",
330 icmp_type (icmp->icmp_type),
331 inet_ntoa (from->sin_addr));
335 if (size < ICMP_MINLEN) {
336 zlog_warn ("ICMP %s packet from %s: IMCP message length is short",
337 icmp_type (icmp->icmp_type),
338 inet_ntoa (from->sin_addr));
345 irdp_solicit_recv (struct stream *s, int size, struct sockaddr_in *from)
347 if (irdp_valid_check (s->data, size, from)) {
354 irdp_advert_recv (struct stream *s, int size, struct sockaddr_in *from)
360 if (irdp_valid_check (s->data, size, from) < 0) {
364 radv.type = stream_getc (s);
365 radv.code = stream_getc (s);
366 radv.checksum = stream_getw (s);
367 radv.number = stream_getc (s);
368 radv.entry = stream_getc (s);
369 radv.lifetime = stream_getw (s);
371 printf ("type : %s\n", icmp_type (radv.type));
372 printf ("number: %d\n", radv.number);
373 printf ("entry: %d\n", radv.entry);
374 printf ("lifetime: %d\n", radv.entry);
376 for (i = 0; i < radv.number; i++)
378 addr.s_addr = stream_getl (s);
379 pref = stream_getl (s);
380 route_add (addr, ntohl (pref));
382 /* Packet size check is needed at here. */
386 irdp_packet_process (char *buf, int size, struct sockaddr_in *from)
391 struct stream *s = NULL;
393 ip = (struct ip *)buf;
394 hlen = ip->ip_hl << 2;
396 if (size < hlen + ICMP_MINLEN)
397 zlog_err ("ICMP relpy length is short\n");
399 icmp = (struct icmp *)(buf + hlen);
401 stream_forward (s, hlen);
403 switch (icmp->icmp_type)
405 case ICMP_ROUTERADVERT:
406 irdp_advert_recv (s, size - hlen, from);
408 case ICMP_ROUTERSOLICIT:
409 irdp_solicit_recv (s, size - hlen, from);
414 /* Make socket for ICMP Router Discovery. */
419 struct protoent *pent;
421 if ((pent = getprotobyname ("icmp")) == NULL) {
422 perror ("getprotobyname");
426 if ((sock = socket (AF_INET, SOCK_RAW, pent->p_proto)) < 0)
439 #define PACKET_BUF 4096
441 struct sockaddr_in from;
443 char buf[PACKET_BUF];
445 fromlen = sizeof (from);
446 nbytes = recvfrom (sock, (char *)buf, PACKET_BUF, 0,
447 (struct sockaddr *)&from, &fromlen);
455 irdp_packet_process (buf, nbytes, &from);
460 /* irdp packet recv loop */
474 "ICMP Router discovery on this interface\n")
479 DEFUN (ip_irdp_multicast,
480 ip_irdp_multicast_cmd,
483 "ICMP Router discovery on this interface\n"
484 "Send IRDP advertisement to the multicast address\n")
489 DEFUN (ip_irdp_holdtime,
490 ip_irdp_holdtime_cmd,
491 "ip irdp holdtime <0-9000>",
493 "ICMP Router discovery on this interface\n"
494 "Set holdtime value\n"
495 "Holdtime value in seconds. Default is 1800 seconds\n")
500 DEFUN (ip_irdp_maxadvertinterval,
501 ip_irdp_maxadvertinterval_cmd,
502 "ip irdp maxadvertinterval (0|<4-1800>)",
504 "ICMP Router discovery on this interface\n"
505 "Set maximum time between advertisement\n"
506 "Maximum advertisement interval in seconds\n")
511 DEFUN (ip_irdp_minadvertinterval,
512 ip_irdp_minadvertinterval_cmd,
513 "ip irdp minadvertinterval <3-1800>",
515 "ICMP Router discovery on this interface\n"
516 "Set minimum time between advertisement\n"
517 "Minimum advertisement interval in seconds\n")
522 DEFUN (ip_irdp_preference,
523 ip_irdp_preference_cmd,
524 /* "ip irdp preference <-2147483648-2147483647>", */
525 "ip irdp preference <0-2147483647>",
527 "ICMP Router discovery on this interface\n"
528 "Set default preference level for this interface\n"
529 "Preference level\n")
535 DEFUN (ip_irdp_address,
537 "ip irdp address A.B.C.D",
539 "ICMP Router discovery on this interface\n"
540 "Specify IRDP address and preference to proxy-advertise\n"
541 "Set IRDP address for proxy-advertise\n")
547 DEFUN (ip_irdp_address_preference,
548 ip_irdp_address_preference_cmd,
549 "ip irdp address A.B.C.D <0-2147483647>",
551 "ICMP Router discovery on this interface\n"
552 "Specify IRDP address and preference to proxy-advertise\n"
553 "Set IRDP address for proxy-advertise\n"
554 "Preference level\n")
562 #ifdef BRCM_CMD_SUPPORT
563 install_element (INTERFACE_NODE, &ip_irdp_cmd);
564 install_element (INTERFACE_NODE, &ip_irdp_multicast_cmd);
565 install_element (INTERFACE_NODE, &ip_irdp_holdtime_cmd);
566 install_element (INTERFACE_NODE, &ip_irdp_maxadvertinterval_cmd);
567 install_element (INTERFACE_NODE, &ip_irdp_minadvertinterval_cmd);
568 install_element (INTERFACE_NODE, &ip_irdp_preference_cmd);
569 install_element (INTERFACE_NODE, &ip_irdp_address_preference_cmd);