]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/irdp_packet.c
3 * Copyright (C) 2000 Robert Olsson.
4 * Swedish University of Agricultural Sciences
6 * This file is part of GNU Zebra.
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
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.
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
25 * This work includes work with the following copywrite:
27 * Copyright (C) 1997, 2000 Kunihiro Ishiguro
32 * Thanks to Jens Låås at Swedish University of Agricultural Sciences
33 * for reviewing and tests.
44 #include "sockunion.h"
50 #include "connected.h"
54 #include "zebra/interface.h"
55 #include "zebra/rtadv.h"
56 #include "zebra/rib.h"
57 #include "zebra/zserv.h"
58 #include "zebra/redistribute.h"
59 #include "zebra/irdp.h"
60 #include <netinet/ip_icmp.h>
62 #include "sockunion.h"
70 char b1
[16], b2
[16], b3
[16], b4
[16]; /* For inet_2a */
72 extern struct zebra_t zebrad
;
73 extern struct thread
*t_irdp_raw
;
74 extern struct interface
*get_iflist_ifp(int idx
);
75 int in_cksum (void *ptr
, int nbytes
);
76 void process_solicit (struct interface
*ifp
);
78 void parse_irdp_packet(char *p
,
80 struct interface
*ifp
)
82 struct ip
*ip
= (struct ip
*)p
;
85 int ip_hlen
, iplen
, datalen
;
87 struct irdp_interface
*irdp
;
97 ip_hlen
= ip
->ip_hl
<< 2;
99 sockopt_iphdrincl_swab_systoh (ip
);
102 datalen
= len
- ip_hlen
;
107 zlog_err ("IRDP: RX length doesnt match IP length");
111 if (iplen
< ICMP_MINLEN
)
113 zlog_err ("IRDP: RX ICMP packet too short from %s\n",
118 /* XXX: RAW doesnt receive link-layer, surely? ??? */
119 /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen +
120 len of IP-header) 14+20 */
121 if (iplen
> IRDP_RX_BUF
-34)
123 zlog_err ("IRDP: RX ICMP packet too long from %s\n",
128 icmp
= (struct icmphdr
*) (p
+ip_hlen
);
130 /* check icmp checksum */
131 if (in_cksum (icmp
, datalen
) != icmp
->checksum
)
133 zlog_warn ("IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
138 /* Handle just only IRDP */
139 if (!(icmp
->type
== ICMP_ROUTERADVERT
140 || icmp
->type
== ICMP_ROUTERSOLICIT
))
145 zlog_warn ("IRDP: RX packet type %d from %s. Bad ICMP type code,"
147 icmp
->type
, inet_ntoa (src
));
151 if (! ((ntohl (ip
->ip_dst
.s_addr
) == INADDR_BROADCAST
)
152 && (irdp
->flags
& IF_BROADCAST
))
154 (ntohl (ip
->ip_dst
.s_addr
) == INADDR_ALLRTRS_GROUP
155 && !(irdp
->flags
& IF_BROADCAST
)))
157 zlog_warn ("IRDP: RX illegal from %s to %s while %s operates in %s\n",
159 ntohl (ip
->ip_dst
.s_addr
) == INADDR_ALLRTRS_GROUP
?
160 "multicast" : inet_ntoa (ip
->ip_dst
),
162 irdp
->flags
& IF_BROADCAST
? "broadcast" : "multicast");
164 zlog_warn ("IRDP: Please correct settings\n");
170 case ICMP_ROUTERADVERT
:
173 case ICMP_ROUTERSOLICIT
:
175 if(irdp
->flags
& IF_DEBUG_MESSAGES
)
176 zlog_warn ("IRDP: RX Solicit on %s from %s\n",
180 process_solicit(ifp
);
184 zlog_warn ("IRDP: RX type %d from %s. Bad ICMP type, silently ignored",
190 int irdp_recvmsg (int sock
, u_char
*buf
, int size
, int *ifindex
)
194 char adata
[CMSG_SPACE( SOPT_SIZE_CMSG_PKTINFO_IPV4() )];
197 msg
.msg_name
= (void *)0;
201 msg
.msg_control
= (void *) adata
;
202 msg
.msg_controllen
= sizeof adata
;
207 ret
= recvmsg (sock
, &msg
, 0);
209 zlog_warn("IRDP: recvmsg: read error %s", safe_strerror(errno
));
213 if (msg
.msg_flags
& MSG_TRUNC
) {
214 zlog_warn("IRDP: recvmsg: truncated message");
217 if (msg
.msg_flags
& MSG_CTRUNC
) {
218 zlog_warn("IRDP: recvmsg: truncated control message");
222 *ifindex
= getsockopt_ifindex (AF_INET
, &msg
);
227 int irdp_read_raw(struct thread
*r
)
229 struct interface
*ifp
;
231 struct irdp_interface
*irdp
;
232 char buf
[IRDP_RX_BUF
];
235 int irdp_sock
= THREAD_FD (r
);
236 t_irdp_raw
= thread_add_read (zebrad
.master
, irdp_read_raw
, NULL
, irdp_sock
);
238 ret
= irdp_recvmsg (irdp_sock
, (u_char
*) buf
, IRDP_RX_BUF
, &ifindex
);
240 if (ret
< 0) zlog_warn ("IRDP: RX Error length = %d", ret
);
242 ifp
= get_iflist_ifp(ifindex
);
243 if(! ifp
) return ret
;
246 if(! zi
) return ret
;
249 if(! irdp
) return ret
;
251 if(! (irdp
->flags
& IF_ACTIVE
)) {
253 if(irdp
->flags
& IF_DEBUG_MISC
)
254 zlog_warn("IRDP: RX ICMP for disabled interface %s\n",
259 if(irdp
->flags
& IF_DEBUG_PACKET
) {
261 zlog_warn("IRDP: RX (idx %d) ", ifindex
);
262 for(i
=0; i
< ret
; i
++) zlog_warn( "IRDP: RX %x ", buf
[i
]&0xFF);
265 parse_irdp_packet(buf
, ret
, ifp
);
271 send_packet(struct interface
*ifp
,
277 static struct sockaddr_in sockdst
= {AF_INET
};
279 struct icmphdr
*icmp
;
281 struct cmsghdr
*cmsg
;
282 struct iovec iovector
;
285 struct in_pktinfo
*pktinfo
;
289 if (!(ifp
->flags
& IFF_UP
))
293 src
= ntohl(p
->u
.prefix4
.s_addr
);
295 src
= 0; /* Is filled in */
297 ip
= (struct ip
*) buf
;
298 ip
->ip_hl
= sizeof(struct ip
) >> 2;
299 ip
->ip_v
= IPVERSION
;
302 ip
->ip_p
= 1; /* IP_ICMP */
304 ip
->ip_src
.s_addr
= src
;
305 ip
->ip_dst
.s_addr
= dst
;
306 icmp
= (struct icmphdr
*) (buf
+ sizeof (struct ip
));
308 /* Merge IP header with icmp packet */
310 stream_get(icmp
, s
, s
->putp
);
312 /* icmp->checksum is already calculated */
313 ip
->ip_len
= sizeof(struct ip
) + s
->putp
;
317 if (setsockopt(irdp_sock
, IPPROTO_IP
, IP_HDRINCL
,
318 (char *) &on
, sizeof(on
)) < 0)
319 zlog_warn("sendto %s", safe_strerror (errno
));
322 if(dst
== INADDR_BROADCAST
) {
324 if (setsockopt(irdp_sock
, SOL_SOCKET
, SO_BROADCAST
,
325 (char *) &on
, sizeof(on
)) < 0)
326 zlog_warn("sendto %s", safe_strerror (errno
));
329 if(dst
!= INADDR_BROADCAST
) {
331 if( setsockopt(irdp_sock
,IPPROTO_IP
, IP_MULTICAST_LOOP
,
332 (char *)&on
,sizeof(on
)) < 0)
333 zlog_warn("sendto %s", safe_strerror (errno
));
336 bzero(&sockdst
,sizeof(sockdst
));
337 sockdst
.sin_family
=AF_INET
;
338 sockdst
.sin_addr
.s_addr
= dst
;
340 cmsg
= (struct cmsghdr
*) (msgbuf
+ sizeof(struct msghdr
));
341 cmsg
->cmsg_len
= sizeof(struct cmsghdr
) + sizeof(struct in_pktinfo
);
342 cmsg
->cmsg_level
= SOL_IP
;
343 cmsg
->cmsg_type
= IP_PKTINFO
;
344 pktinfo
= (struct in_pktinfo
*) CMSG_DATA(cmsg
);
345 pktinfo
->ipi_ifindex
= ifp
->ifindex
;
346 pktinfo
->ipi_spec_dst
.s_addr
= src
;
347 pktinfo
->ipi_addr
.s_addr
= src
;
349 iovector
.iov_base
= (void *) buf
;
350 iovector
.iov_len
= ip
->ip_len
;
351 msg
= (struct msghdr
*) msgbuf
;
352 msg
->msg_name
= &sockdst
;
353 msg
->msg_namelen
= sizeof(sockdst
);
354 msg
->msg_iov
= &iovector
;
356 msg
->msg_control
= cmsg
;
357 msg
->msg_controllen
= cmsg
->cmsg_len
;
359 sockopt_iphdrincl_swab_htosys (ip
);
361 if (sendmsg(irdp_sock
, msg
, 0) < 0) {
362 zlog_warn("sendto %s", safe_strerror (errno
));
364 /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
368 #endif /* HAVE_IRDP */