2 * Copyright (C) 1999 Yasuhiro Ohara
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
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include "sockunion.h"
28 #include "ospf6_proto.h"
31 extern struct sockaddr_in6 allspfrouters6
;
32 extern struct sockaddr_in6 alldrouters6
;
33 extern int ospf6_sock
;
34 extern struct thread_master
*master
;
38 iov_clear (struct iovec
*iov
, size_t iovlen
)
41 for (i
= 0; i
< iovlen
; i
++)
43 iov
[i
].iov_base
= NULL
;
49 iov_count (struct iovec
*iov
)
52 for (i
= 0; iov
[i
].iov_base
; i
++)
58 iov_totallen (struct iovec
*iov
)
62 for (i
= 0; iov
[i
].iov_base
; i
++)
63 totallen
+= iov
[i
].iov_len
;
68 iov_prepend (int mtype
, struct iovec
*iov
, size_t len
)
73 base
= (void *) XMALLOC (mtype
, len
);
76 zlog_warn ("Network: iov_prepend failed");
79 memset (base
, 0, len
);
81 iovlen
= iov_count (iov
);
82 for (i
= iovlen
; i
; i
--)
84 iov
[i
].iov_base
= iov
[i
- 1].iov_base
;
85 iov
[i
].iov_len
= iov
[i
- 1].iov_len
;
87 iov
[0].iov_base
= (char *)base
;
94 iov_append (int mtype
, struct iovec
*iov
, size_t len
)
99 base
= (void *)XMALLOC (mtype
, len
);
102 zlog_warn ("Network: iov_append failed");
105 memset (base
, 0, len
);
107 /* proceed to the end */
110 iov
[i
].iov_base
= (char *)base
;
111 iov
[i
].iov_len
= len
;
117 iov_attach_last (struct iovec
*iov
, void *base
, size_t len
)
121 iov
[i
].iov_base
= (char *)base
;
122 iov
[i
].iov_len
= len
;
127 iov_detach_first (struct iovec
*iov
)
133 base
= iov
[0].iov_base
;
134 len
= iov
[0].iov_len
;
135 iovlen
= iov_count (iov
);
136 for (i
= 0; i
< iovlen
; i
++)
138 iov
[i
].iov_base
= iov
[i
+ 1].iov_base
;
139 iov
[i
].iov_len
= iov
[i
+ 1].iov_len
;
145 iov_free (int mtype
, struct iovec
*iov
, u_int begin
, u_int end
)
149 for (i
= begin
; i
< end
; i
++)
151 XFREE (mtype
, iov
[i
].iov_base
);
152 iov
[i
].iov_base
= NULL
;
160 iov_trim_head (int mtype
, struct iovec
*iov
)
164 base
= iov_detach_first (iov
);
170 iov_free_all (int mtype
, struct iovec
*iov
)
172 int i
, end
= iov_count (iov
);
173 for (i
= 0; i
< end
; i
++)
175 XFREE (mtype
, iov
[i
].iov_base
);
176 iov
[i
].iov_base
= NULL
;
182 iov_copy_all (struct iovec
*dst
, struct iovec
*src
, size_t size
)
185 for (i
= 0; i
< size
; i
++)
187 dst
[i
].iov_base
= src
[i
].iov_base
;
188 dst
[i
].iov_len
= src
[i
].iov_len
;
193 /* Make ospf6d's server socket. */
197 ospf6_sock
= socket (AF_INET6
, SOCK_RAW
, IPPROTO_OSPFIGP
);
200 zlog_warn ("Network: can't create OSPF6 socket.");
203 sockopt_reuseaddr (ospf6_sock
);
205 /* setup global sockaddr_in6, allspf6 & alldr6 for later use */
206 allspfrouters6
.sin6_family
= AF_INET6
;
207 alldrouters6
.sin6_family
= AF_INET6
;
209 allspfrouters6
.sin6_len
= sizeof (struct sockaddr_in6
);
210 alldrouters6
.sin6_len
= sizeof (struct sockaddr_in6
);
211 #endif /* SIN6_LEN */
212 inet_pton (AF_INET6
, ALLSPFROUTERS6
, &allspfrouters6
.sin6_addr
);
213 inet_pton (AF_INET6
, ALLDROUTERS6
, &alldrouters6
.sin6_addr
);
218 /* returns 0 if succeed, else returns -1 */
220 ospf6_join_allspfrouters (u_int ifindex
)
222 struct ipv6_mreq mreq6
;
226 mreq6
.ipv6mr_interface
= ifindex
;
227 memcpy (&mreq6
.ipv6mr_multiaddr
, &allspfrouters6
.sin6_addr
,
228 sizeof (struct in6_addr
));
230 retval
= setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
231 &mreq6
, sizeof (mreq6
));
234 zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
235 ifindex
, strerror (errno
));
238 zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex
);
245 ospf6_leave_allspfrouters (u_int ifindex
)
247 struct ipv6_mreq mreq6
;
250 mreq6
.ipv6mr_interface
= ifindex
;
251 memcpy (&mreq6
.ipv6mr_multiaddr
, &allspfrouters6
.sin6_addr
,
252 sizeof (struct in6_addr
));
254 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
255 &mreq6
, sizeof (mreq6
)) < 0)
256 zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
257 ifindex
, strerror (errno
));
259 zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex
);
263 ospf6_join_alldrouters (u_int ifindex
)
265 struct ipv6_mreq mreq6
;
268 mreq6
.ipv6mr_interface
= ifindex
;
269 memcpy (&mreq6
.ipv6mr_multiaddr
, &alldrouters6
.sin6_addr
,
270 sizeof (struct in6_addr
));
272 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_JOIN_GROUP
,
273 &mreq6
, sizeof (mreq6
)) < 0)
274 zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
275 ifindex
, strerror (errno
));
277 zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex
);
281 ospf6_leave_alldrouters (u_int ifindex
)
283 struct ipv6_mreq mreq6
;
286 mreq6
.ipv6mr_interface
= ifindex
;
287 memcpy (&mreq6
.ipv6mr_multiaddr
, &alldrouters6
.sin6_addr
,
288 sizeof (struct in6_addr
));
290 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_LEAVE_GROUP
,
291 &mreq6
, sizeof (mreq6
)) < 0)
292 zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex
);
294 zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex
);
297 /* setsockopt ReUseAddr to on */
299 ospf6_set_reuseaddr ()
302 if (setsockopt (ospf6_sock
, SOL_SOCKET
, SO_REUSEADDR
, &on
,
304 zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno
));
307 /* setsockopt MulticastLoop to off */
309 ospf6_reset_mcastloop ()
312 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_MULTICAST_LOOP
,
313 &off
, sizeof (u_int
)) < 0)
314 zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
322 #ifdef IPV6_RECVPKTINFO /*2292bis-01*/
323 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_RECVPKTINFO
,
324 &on
, sizeof (u_int
)) < 0)
325 zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno
));
327 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_PKTINFO
,
328 &on
, sizeof (u_int
)) < 0)
329 zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno
));
334 ospf6_set_checksum ()
337 #if !defined(DISABLE_IPV6_CHECKSUM)
338 if (setsockopt (ospf6_sock
, IPPROTO_IPV6
, IPV6_CHECKSUM
,
339 &offset
, sizeof (offset
)) < 0)
340 zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno
));
342 zlog_warn ("Network: Don't set IPV6_CHECKSUM");
343 #endif /* DISABLE_IPV6_CHECKSUM */
347 ospf6_sendmsg (struct in6_addr
*src
, struct in6_addr
*dst
,
348 unsigned int *ifindex
, struct iovec
*message
)
351 struct msghdr smsghdr
;
352 struct cmsghdr
*scmsgp
;
353 u_char cmsgbuf
[CMSG_SPACE(sizeof (struct in6_pktinfo
))];
354 struct in6_pktinfo
*pktinfo
;
355 struct sockaddr_in6 dst_sin6
;
360 scmsgp
= (struct cmsghdr
*)cmsgbuf
;
361 pktinfo
= (struct in6_pktinfo
*)(CMSG_DATA(scmsgp
));
362 memset (&dst_sin6
, 0, sizeof (struct sockaddr_in6
));
365 pktinfo
->ipi6_ifindex
= *ifindex
;
367 memcpy (&pktinfo
->ipi6_addr
, src
, sizeof (struct in6_addr
));
369 memset (&pktinfo
->ipi6_addr
, 0, sizeof (struct in6_addr
));
371 /* destination address */
372 dst_sin6
.sin6_family
= AF_INET6
;
374 dst_sin6
.sin6_len
= sizeof (struct sockaddr_in6
);
376 memcpy (&dst_sin6
.sin6_addr
, dst
, sizeof (struct in6_addr
));
377 #ifdef HAVE_SIN6_SCOPE_ID
378 dst_sin6
.sin6_scope_id
= *ifindex
;
381 /* send control msg */
382 scmsgp
->cmsg_level
= IPPROTO_IPV6
;
383 scmsgp
->cmsg_type
= IPV6_PKTINFO
;
384 scmsgp
->cmsg_len
= CMSG_LEN (sizeof (struct in6_pktinfo
));
385 /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
388 smsghdr
.msg_iov
= message
;
389 smsghdr
.msg_iovlen
= iov_count (message
);
390 smsghdr
.msg_name
= (caddr_t
) &dst_sin6
;
391 smsghdr
.msg_namelen
= sizeof (struct sockaddr_in6
);
392 smsghdr
.msg_control
= (caddr_t
) cmsgbuf
;
393 smsghdr
.msg_controllen
= sizeof (cmsgbuf
);
395 retval
= sendmsg (ospf6_sock
, &smsghdr
, 0);
396 if (retval
!= iov_totallen (message
))
397 zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",
398 *ifindex
, strerror (errno
), errno
);
402 ospf6_recvmsg (struct in6_addr
*src
, struct in6_addr
*dst
,
403 unsigned int *ifindex
, struct iovec
*message
)
406 struct msghdr rmsghdr
;
407 struct cmsghdr
*rcmsgp
;
408 u_char cmsgbuf
[CMSG_SPACE(sizeof (struct in6_pktinfo
))];
409 struct in6_pktinfo
*pktinfo
;
410 struct sockaddr_in6 src_sin6
;
412 rcmsgp
= (struct cmsghdr
*)cmsgbuf
;
413 pktinfo
= (struct in6_pktinfo
*)(CMSG_DATA(rcmsgp
));
414 memset (&src_sin6
, 0, sizeof (struct sockaddr_in6
));
416 /* receive control msg */
417 rcmsgp
->cmsg_level
= IPPROTO_IPV6
;
418 rcmsgp
->cmsg_type
= IPV6_PKTINFO
;
419 rcmsgp
->cmsg_len
= CMSG_LEN (sizeof (struct in6_pktinfo
));
420 /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
422 /* receive msg hdr */
423 rmsghdr
.msg_iov
= message
;
424 rmsghdr
.msg_iovlen
= iov_count (message
);
425 rmsghdr
.msg_name
= (caddr_t
) &src_sin6
;
426 rmsghdr
.msg_namelen
= sizeof (struct sockaddr_in6
);
427 rmsghdr
.msg_control
= (caddr_t
) cmsgbuf
;
428 rmsghdr
.msg_controllen
= sizeof (cmsgbuf
);
430 retval
= recvmsg (ospf6_sock
, &rmsghdr
, 0);
433 zlog_warn ("Network: recvmsg failed: %s", strerror (errno
));
435 else if (retval
== iov_totallen (message
))
437 zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",
438 retval
, iov_totallen (message
));
443 memcpy (src
, &src_sin6
.sin6_addr
, sizeof (struct in6_addr
));
445 /* destination address */
447 *ifindex
= pktinfo
->ipi6_ifindex
;
449 memcpy (dst
, &pktinfo
->ipi6_addr
, sizeof (struct in6_addr
));
453 ospf6_recvmsg_peek (struct in6_addr
*src
, struct in6_addr
*dst
,
454 unsigned int *ifindex
, struct iovec
*message
)
457 struct msghdr rmsghdr
;
458 struct cmsghdr
*rcmsgp
;
459 u_char cmsgbuf
[CMSG_SPACE(sizeof (struct in6_pktinfo
))];
460 struct in6_pktinfo
*pktinfo
;
461 struct sockaddr_in6 src_sin6
;
463 rcmsgp
= (struct cmsghdr
*)cmsgbuf
;
464 pktinfo
= (struct in6_pktinfo
*)(CMSG_DATA(rcmsgp
));
465 memset (&src_sin6
, 0, sizeof (struct sockaddr_in6
));
467 /* receive control msg */
468 rcmsgp
->cmsg_level
= IPPROTO_IPV6
;
469 rcmsgp
->cmsg_type
= IPV6_PKTINFO
;
470 rcmsgp
->cmsg_len
= CMSG_LEN (sizeof (struct in6_pktinfo
));
471 /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
473 /* receive msg hdr */
474 rmsghdr
.msg_iov
= message
;
475 rmsghdr
.msg_iovlen
= iov_count (message
);
476 rmsghdr
.msg_name
= (caddr_t
) &src_sin6
;
477 rmsghdr
.msg_namelen
= sizeof (struct sockaddr_in6
);
478 rmsghdr
.msg_control
= (caddr_t
) cmsgbuf
;
479 rmsghdr
.msg_controllen
= sizeof (cmsgbuf
);
481 retval
= recvmsg (ospf6_sock
, &rmsghdr
, MSG_PEEK
);
482 if (retval
!= iov_totallen (message
))
483 zlog_warn ("Network: recvmsg failed: %s", strerror (errno
));
487 memcpy (src
, &src_sin6
.sin6_addr
, sizeof (struct in6_addr
));
489 /* destination address */
491 *ifindex
= pktinfo
->ipi6_ifindex
;
493 memcpy (dst
, &pktinfo
->ipi6_addr
, sizeof (struct in6_addr
));