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"
29
#include "ospf6_proto.h"
32
extern struct sockaddr_in6 allspfrouters6;
33
extern struct sockaddr_in6 alldrouters6;
34
extern int ospf6_sock;
35
extern struct thread_master *master;
36
extern struct zebra_privs_t ospf6d_privs;
40
iov_clear (struct iovec *iov, size_t iovlen)
43
for (i = 0; i < iovlen; i++)
45
iov[i].iov_base = NULL;
51
iov_count (struct iovec *iov)
54
for (i = 0; iov[i].iov_base; i++)
60
iov_totallen (struct iovec *iov)
64
for (i = 0; iov[i].iov_base; i++)
65
totallen += iov[i].iov_len;
70
iov_prepend (int mtype, struct iovec *iov, size_t len)
75
base = (void *) XMALLOC (mtype, len);
78
zlog_warn ("Network: iov_prepend failed");
81
memset (base, 0, len);
83
iovlen = iov_count (iov);
84
for (i = iovlen; i; i--)
86
iov[i].iov_base = iov[i - 1].iov_base;
87
iov[i].iov_len = iov[i - 1].iov_len;
89
iov[0].iov_base = (char *)base;
96
iov_append (int mtype, struct iovec *iov, size_t len)
101
base = (void *)XMALLOC (mtype, len);
104
zlog_warn ("Network: iov_append failed");
107
memset (base, 0, len);
109
/* proceed to the end */
112
iov[i].iov_base = (char *)base;
113
iov[i].iov_len = len;
119
iov_attach_last (struct iovec *iov, void *base, size_t len)
123
iov[i].iov_base = (char *)base;
124
iov[i].iov_len = len;
129
iov_detach_first (struct iovec *iov)
135
base = iov[0].iov_base;
136
len = iov[0].iov_len;
137
iovlen = iov_count (iov);
138
for (i = 0; i < iovlen; i++)
140
iov[i].iov_base = iov[i + 1].iov_base;
141
iov[i].iov_len = iov[i + 1].iov_len;
147
iov_free (int mtype, struct iovec *iov, u_int begin, u_int end)
151
for (i = begin; i < end; i++)
153
XFREE (mtype, iov[i].iov_base);
154
iov[i].iov_base = NULL;
162
iov_trim_head (int mtype, struct iovec *iov)
166
base = iov_detach_first (iov);
172
iov_free_all (int mtype, struct iovec *iov)
174
int i, end = iov_count (iov);
175
for (i = 0; i < end; i++)
177
XFREE (mtype, iov[i].iov_base);
178
iov[i].iov_base = NULL;
184
iov_copy_all (struct iovec *dst, struct iovec *src, size_t size)
187
for (i = 0; i < size; i++)
189
dst[i].iov_base = src[i].iov_base;
190
dst[i].iov_len = src[i].iov_len;
195
/* Make ospf6d's server socket. */
200
if (ospf6d_privs.change (ZPRIVS_RAISE))
201
zlog_err ("ospf6_serv_sock: could not raise privs");
203
ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
206
zlog_warn ("Network: can't create OSPF6 socket.");
209
sockopt_reuseaddr (ospf6_sock);
211
if (ospf6d_privs.change (ZPRIVS_LOWER))
212
zlog_err ("ospf_sock_init: could not lower privs");
214
/* setup global sockaddr_in6, allspf6 & alldr6 for later use */
215
allspfrouters6.sin6_family = AF_INET6;
216
alldrouters6.sin6_family = AF_INET6;
218
allspfrouters6.sin6_len = sizeof (struct sockaddr_in6);
219
alldrouters6.sin6_len = sizeof (struct sockaddr_in6);
220
#endif /* SIN6_LEN */
221
inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6.sin6_addr);
222
inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6.sin6_addr);
227
/* returns 0 if succeed, else returns -1 */
229
ospf6_join_allspfrouters (u_int ifindex)
231
struct ipv6_mreq mreq6;
235
mreq6.ipv6mr_interface = ifindex;
236
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
237
sizeof (struct in6_addr));
239
retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
240
&mreq6, sizeof (mreq6));
243
zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
244
ifindex, strerror (errno));
247
zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
254
ospf6_leave_allspfrouters (u_int ifindex)
256
struct ipv6_mreq mreq6;
259
mreq6.ipv6mr_interface = ifindex;
260
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
261
sizeof (struct in6_addr));
263
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
264
&mreq6, sizeof (mreq6)) < 0)
265
zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
266
ifindex, strerror (errno));
268
zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
272
ospf6_join_alldrouters (u_int ifindex)
274
struct ipv6_mreq mreq6;
277
mreq6.ipv6mr_interface = ifindex;
278
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
279
sizeof (struct in6_addr));
281
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
282
&mreq6, sizeof (mreq6)) < 0)
283
zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
284
ifindex, strerror (errno));
286
zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
290
ospf6_leave_alldrouters (u_int ifindex)
292
struct ipv6_mreq mreq6;
295
mreq6.ipv6mr_interface = ifindex;
296
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
297
sizeof (struct in6_addr));
299
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
300
&mreq6, sizeof (mreq6)) < 0)
301
zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
303
zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
306
/* setsockopt ReUseAddr to on */
308
ospf6_set_reuseaddr ()
311
if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on,
313
zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno));
316
/* setsockopt MulticastLoop to off */
318
ospf6_reset_mcastloop ()
321
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
322
&off, sizeof (u_int)) < 0)
323
zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
331
#ifdef IPV6_RECVPKTINFO /*2292bis-01*/
332
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
333
&on, sizeof (u_int)) < 0)
334
zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno));
336
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO,
337
&on, sizeof (u_int)) < 0)
338
zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno));
343
ospf6_set_checksum ()
346
#if !defined(DISABLE_IPV6_CHECKSUM)
347
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
348
&offset, sizeof (offset)) < 0)
349
zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
351
zlog_warn ("Network: Don't set IPV6_CHECKSUM");
352
#endif /* DISABLE_IPV6_CHECKSUM */
356
ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
357
unsigned int *ifindex, struct iovec *message)
360
struct msghdr smsghdr;
361
struct cmsghdr *scmsgp;
362
u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
363
struct in6_pktinfo *pktinfo;
364
struct sockaddr_in6 dst_sin6;
369
scmsgp = (struct cmsghdr *)cmsgbuf;
370
pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
371
memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));
374
pktinfo->ipi6_ifindex = *ifindex;
376
memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
378
memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));
380
/* destination address */
381
dst_sin6.sin6_family = AF_INET6;
383
dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
385
memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
386
#ifdef HAVE_SIN6_SCOPE_ID
387
dst_sin6.sin6_scope_id = *ifindex;
390
/* send control msg */
391
scmsgp->cmsg_level = IPPROTO_IPV6;
392
scmsgp->cmsg_type = IPV6_PKTINFO;
393
scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
394
/* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
397
smsghdr.msg_iov = message;
398
smsghdr.msg_iovlen = iov_count (message);
399
smsghdr.msg_name = (caddr_t) &dst_sin6;
400
smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
401
smsghdr.msg_control = (caddr_t) cmsgbuf;
402
smsghdr.msg_controllen = sizeof (cmsgbuf);
404
retval = sendmsg (ospf6_sock, &smsghdr, 0);
405
if (retval != iov_totallen (message))
406
zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",
407
*ifindex, strerror (errno), errno);
411
ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
412
unsigned int *ifindex, struct iovec *message)
415
struct msghdr rmsghdr;
416
struct cmsghdr *rcmsgp;
417
u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
418
struct in6_pktinfo *pktinfo;
419
struct sockaddr_in6 src_sin6;
421
rcmsgp = (struct cmsghdr *)cmsgbuf;
422
pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
423
memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
425
/* receive control msg */
426
rcmsgp->cmsg_level = IPPROTO_IPV6;
427
rcmsgp->cmsg_type = IPV6_PKTINFO;
428
rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
429
/* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
431
/* receive msg hdr */
432
rmsghdr.msg_iov = message;
433
rmsghdr.msg_iovlen = iov_count (message);
434
rmsghdr.msg_name = (caddr_t) &src_sin6;
435
rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
436
rmsghdr.msg_control = (caddr_t) cmsgbuf;
437
rmsghdr.msg_controllen = sizeof (cmsgbuf);
439
retval = recvmsg (ospf6_sock, &rmsghdr, 0);
442
zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
444
else if (retval == iov_totallen (message))
446
zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",
447
retval, iov_totallen (message));
452
memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
454
/* destination address */
456
*ifindex = pktinfo->ipi6_ifindex;
458
memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
462
ospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,
463
unsigned int *ifindex, struct iovec *message)
466
struct msghdr rmsghdr;
467
struct cmsghdr *rcmsgp;
468
u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
469
struct in6_pktinfo *pktinfo;
470
struct sockaddr_in6 src_sin6;
472
rcmsgp = (struct cmsghdr *)cmsgbuf;
473
pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
474
memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
476
/* receive control msg */
477
rcmsgp->cmsg_level = IPPROTO_IPV6;
478
rcmsgp->cmsg_type = IPV6_PKTINFO;
479
rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
480
/* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
482
/* receive msg hdr */
483
rmsghdr.msg_iov = message;
484
rmsghdr.msg_iovlen = iov_count (message);
485
rmsghdr.msg_name = (caddr_t) &src_sin6;
486
rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
487
rmsghdr.msg_control = (caddr_t) cmsgbuf;
488
rmsghdr.msg_controllen = sizeof (cmsgbuf);
490
retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);
491
if (retval != iov_totallen (message))
492
zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
496
memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
498
/* destination address */
500
*ifindex = pktinfo->ipi6_ifindex;
502
memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));