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 install_element (INTERFACE_NODE
, &ip_irdp_cmd
);
563 install_element (INTERFACE_NODE
, &ip_irdp_multicast_cmd
);
564 install_element (INTERFACE_NODE
, &ip_irdp_holdtime_cmd
);
565 install_element (INTERFACE_NODE
, &ip_irdp_maxadvertinterval_cmd
);
566 install_element (INTERFACE_NODE
, &ip_irdp_minadvertinterval_cmd
);
567 install_element (INTERFACE_NODE
, &ip_irdp_preference_cmd
);
568 install_element (INTERFACE_NODE
, &ip_irdp_address_preference_cmd
);