⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ospf6_network.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
字号:
/* * Copyright (C) 1999 Yasuhiro Ohara * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,  * Boston, MA 02111-1307, USA.   */#include <zebra.h>#include "memory.h"#include "log.h"#include "sockunion.h"#include "ospf6d.h"#include "ospf6_proto.h"extern int errno;extern struct sockaddr_in6 allspfrouters6;extern struct sockaddr_in6 alldrouters6;extern int ospf6_sock;extern struct thread_master *master;/* iovec functions */voidiov_clear (struct iovec *iov, size_t iovlen){  int i;  for (i = 0; i < iovlen; i++)    {      iov[i].iov_base = NULL;      iov[i].iov_len = 0;    }}intiov_count (struct iovec *iov){  int i;  for (i = 0; iov[i].iov_base; i++)    ;  return i;}intiov_totallen (struct iovec *iov){  int i;  int totallen = 0;  for (i = 0; iov[i].iov_base; i++)    totallen += iov[i].iov_len;  return totallen;}void *iov_prepend (int mtype, struct iovec *iov, size_t len){  int i, iovlen;  void *base;  base = (void *) XMALLOC (mtype, len);  if (!base)    {      zlog_warn ("Network: iov_prepend failed");      return NULL;    }  memset (base, 0, len);  iovlen = iov_count (iov);  for (i = iovlen; i; i--)    {      iov[i].iov_base = iov[i - 1].iov_base;      iov[i].iov_len = iov[i - 1].iov_len;    }  iov[0].iov_base = (char *)base;  iov[0].iov_len = len;  return base;}void *iov_append (int mtype, struct iovec *iov, size_t len){  int i;  void *base;  base = (void *)XMALLOC (mtype, len);  if (!base)    {      zlog_warn ("Network: iov_append failed");      return NULL;    }  memset (base, 0, len);  /* proceed to the end */  i = iov_count (iov);  iov[i].iov_base = (char *)base;  iov[i].iov_len = len;  return base;}void *iov_attach_last (struct iovec *iov, void *base, size_t len){  int i;  i = iov_count (iov);  iov[i].iov_base = (char *)base;  iov[i].iov_len = len;  return base;}void *iov_detach_first (struct iovec *iov){  int i, iovlen;  void *base;  size_t len;  base = iov[0].iov_base;  len = iov[0].iov_len;  iovlen = iov_count (iov);  for (i = 0; i < iovlen; i++)    {      iov[i].iov_base = iov[i + 1].iov_base;      iov[i].iov_len = iov[i + 1].iov_len;    }  return base;}intiov_free (int mtype, struct iovec *iov, u_int begin, u_int end){  int i;  for (i = begin; i < end; i++)    {      XFREE (mtype, iov[i].iov_base);      iov[i].iov_base = NULL;      iov[i].iov_len = 0;    }  return 0;}voidiov_trim_head (int mtype, struct iovec *iov){  void *base;  base = iov_detach_first (iov);  XFREE (mtype, base);  return;}voidiov_free_all (int mtype, struct iovec *iov){  int i, end = iov_count (iov);  for (i = 0; i < end; i++)    {      XFREE (mtype, iov[i].iov_base);      iov[i].iov_base = NULL;      iov[i].iov_len = 0;    }}voidiov_copy_all (struct iovec *dst, struct iovec *src, size_t size){  int i;  for (i = 0; i < size; i++)    {      dst[i].iov_base = src[i].iov_base;      dst[i].iov_len = src[i].iov_len;    }}/* Make ospf6d's server socket. */intospf6_serv_sock (){  ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);  if (ospf6_sock < 0)    {      zlog_warn ("Network: can't create OSPF6 socket.");      return -1;    }  sockopt_reuseaddr (ospf6_sock);  /* setup global sockaddr_in6, allspf6 & alldr6 for later use */  allspfrouters6.sin6_family = AF_INET6;  alldrouters6.sin6_family = AF_INET6;#ifdef SIN6_LEN  allspfrouters6.sin6_len = sizeof (struct sockaddr_in6);  alldrouters6.sin6_len = sizeof (struct sockaddr_in6);#endif /* SIN6_LEN */  inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6.sin6_addr);  inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6.sin6_addr);  return 0;}/* returns 0 if succeed, else returns -1 */intospf6_join_allspfrouters (u_int ifindex){  struct ipv6_mreq mreq6;  int retval;  assert (ifindex);  mreq6.ipv6mr_interface = ifindex;  memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,          sizeof (struct in6_addr));  retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,                       &mreq6, sizeof (mreq6));  if (retval < 0)    zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",               ifindex, strerror (errno));#if 0  else    zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);#endif  return retval;}voidospf6_leave_allspfrouters (u_int ifindex){  struct ipv6_mreq mreq6;  assert (ifindex);  mreq6.ipv6mr_interface = ifindex;  memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,          sizeof (struct in6_addr));  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,                  &mreq6, sizeof (mreq6)) < 0)    zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",               ifindex, strerror (errno));#if 0  else    zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);#endif}voidospf6_join_alldrouters (u_int ifindex){  struct ipv6_mreq mreq6;  assert (ifindex);  mreq6.ipv6mr_interface = ifindex;  memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,          sizeof (struct in6_addr));  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,                  &mreq6, sizeof (mreq6)) < 0)    zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",               ifindex, strerror (errno));#if 0  else    zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);#endif}voidospf6_leave_alldrouters (u_int ifindex){  struct ipv6_mreq mreq6;  assert (ifindex);  mreq6.ipv6mr_interface = ifindex;  memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,          sizeof (struct in6_addr));  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,                  &mreq6, sizeof (mreq6)) < 0)    zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);#if 0  else    zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);#endif}/* setsockopt ReUseAddr to on */voidospf6_set_reuseaddr (){  u_int on = 0;  if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on,                  sizeof (u_int)) < 0)    zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno));}/* setsockopt MulticastLoop to off */voidospf6_reset_mcastloop (){  u_int off = 0;  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,                  &off, sizeof (u_int)) < 0)    zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",               strerror (errno));}voidospf6_set_pktinfo (){  u_int on = 1;#ifdef IPV6_RECVPKTINFO	/*2292bis-01*/  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,                  &on, sizeof (u_int)) < 0)    zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno));#else /*RFC2292*/  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO,                  &on, sizeof (u_int)) < 0)    zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno));#endif}voidospf6_set_checksum (){  int offset = 12;#ifndef DISABLE_IPV6_CHECKSUM  if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,                  &offset, sizeof (offset)) < 0)    zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));#else  zlog_warn ("Network: Don't set IPV6_CHECKSUM");#endif /* DISABLE_IPV6_CHECKSUM */}voidospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,               unsigned int *ifindex, struct iovec *message){  int retval;  struct msghdr smsghdr;  struct cmsghdr *scmsgp;  u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];  struct in6_pktinfo *pktinfo;  struct sockaddr_in6 dst_sin6;  assert (dst);  assert (*ifindex);  scmsgp = (struct cmsghdr *)cmsgbuf;  pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));  memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));  /* source address */  pktinfo->ipi6_ifindex = *ifindex;  if (src)    memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));  else    memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));  /* destination address */  dst_sin6.sin6_family = AF_INET6;#ifdef SIN6_LEN  dst_sin6.sin6_len = sizeof (struct sockaddr_in6);#endif /*SIN6_LEN*/  memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));#ifdef HAVE_SIN6_SCOPE_ID  dst_sin6.sin6_scope_id = *ifindex;#endif  /* send control msg */  scmsgp->cmsg_level = IPPROTO_IPV6;  scmsgp->cmsg_type = IPV6_PKTINFO;  scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));  /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */  /* send msg hdr */  smsghdr.msg_iov = message;  smsghdr.msg_iovlen = iov_count (message);  smsghdr.msg_name = (caddr_t) &dst_sin6;  smsghdr.msg_namelen = sizeof (struct sockaddr_in6);  smsghdr.msg_control = (caddr_t) cmsgbuf;  smsghdr.msg_controllen = sizeof (cmsgbuf);  retval = sendmsg (ospf6_sock, &smsghdr, 0);  if (retval != iov_totallen (message))    zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",               *ifindex, strerror (errno), errno);}voidospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,               unsigned int *ifindex, struct iovec *message){  int retval;  struct msghdr rmsghdr;  struct cmsghdr *rcmsgp;  u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];  struct in6_pktinfo *pktinfo;  struct sockaddr_in6 src_sin6;  rcmsgp = (struct cmsghdr *)cmsgbuf;  pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));  memset (&src_sin6, 0, sizeof (struct sockaddr_in6));  /* receive control msg */  rcmsgp->cmsg_level = IPPROTO_IPV6;  rcmsgp->cmsg_type = IPV6_PKTINFO;  rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));  /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */  /* receive msg hdr */  rmsghdr.msg_iov = message;  rmsghdr.msg_iovlen = iov_count (message);  rmsghdr.msg_name = (caddr_t) &src_sin6;  rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);  rmsghdr.msg_control = (caddr_t) cmsgbuf;  rmsghdr.msg_controllen = sizeof (cmsgbuf);  retval = recvmsg (ospf6_sock, &rmsghdr, 0);  if (retval < 0)    {      zlog_warn ("Network: recvmsg failed: %s", strerror (errno));    }  else if (retval == iov_totallen (message))    {      zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",                  retval, iov_totallen (message));    }  /* source address */  assert (src);  memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));  /* destination address */  if (ifindex)    *ifindex = pktinfo->ipi6_ifindex;  if (dst)    memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));}voidospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,                    unsigned int *ifindex, struct iovec *message){  int retval;  struct msghdr rmsghdr;  struct cmsghdr *rcmsgp;  u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];  struct in6_pktinfo *pktinfo;  struct sockaddr_in6 src_sin6;  rcmsgp = (struct cmsghdr *)cmsgbuf;  pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));  memset (&src_sin6, 0, sizeof (struct sockaddr_in6));  /* receive control msg */  rcmsgp->cmsg_level = IPPROTO_IPV6;  rcmsgp->cmsg_type = IPV6_PKTINFO;  rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));  /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */  /* receive msg hdr */  rmsghdr.msg_iov = message;  rmsghdr.msg_iovlen = iov_count (message);  rmsghdr.msg_name = (caddr_t) &src_sin6;  rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);  rmsghdr.msg_control = (caddr_t) cmsgbuf;  rmsghdr.msg_controllen = sizeof (cmsgbuf);  retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);  if (retval != iov_totallen (message))    zlog_warn ("Network: recvmsg failed: %s", strerror (errno));  /* source address */  assert (src);  memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));  /* destination address */  if (ifindex)    *ifindex = pktinfo->ipi6_ifindex;  if (dst)    memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -