📄 kernel_socket.c
字号:
memcpy ((caddr_t)(X), pnt, len); \ pnt += len; \ } /* Be sure structure is cleared */ memset (dest, 0, sizeof (union sockunion)); memset (gate, 0, sizeof (union sockunion)); memset (mask, 0, sizeof (union sockunion)); /* We fetch each socket variable into sockunion. */ RTMADDRGET (dest, RTA_DST); RTMADDRGET (gate, RTA_GATEWAY); RTMMASKGET (mask, RTA_NETMASK); RTMADDRGET (NULL, RTA_GENMASK); RTMADDRGET (NULL, RTA_IFP); RTMADDRGET (NULL, RTA_IFA); RTMADDRGET (NULL, RTA_AUTHOR); RTMADDRGET (NULL, RTA_BRD); /* If there is netmask information set it's family same as destination family*/ if (rtm->rtm_addrs & RTA_NETMASK) mask->sa.sa_family = dest->sa.sa_family; /* Assert read up to the end of pointer. */ if (pnt != end) zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data."); return rtm->rtm_flags;}voidrtm_read (struct rt_msghdr *rtm){ int flags; u_char zebra_flags; union sockunion dest, mask, gate; zebra_flags = 0; /* Discard self send message. */ if (rtm->rtm_type != RTM_GET && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid)) return; /* Read destination and netmask and gateway from rtm message structure. */ flags = rtm_read_mesg (rtm, &dest, &mask, &gate);#ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ if (flags & RTF_CLONED) return;#endif#ifdef RTF_WASCLONED /*freebsd*/ if (flags & RTF_WASCLONED) return;#endif if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP)) return; /* This is connected route. */ if (! (flags & RTF_GATEWAY)) return; if (flags & RTF_PROTO1) SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE); /* This is persistent route. */ if (flags & RTF_STATIC) SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC); if (dest.sa.sa_family == AF_INET) { struct prefix_ipv4 p; p.family = AF_INET; p.prefix = dest.sin.sin_addr; if (flags & RTF_HOST) p.prefixlen = IPV4_MAX_PREFIXLEN; else p.prefixlen = ip_masklen (mask.sin.sin_addr); if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0, 0, 0); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0); }#ifdef HAVE_IPV6 if (dest.sa.sa_family == AF_INET6) { struct prefix_ipv6 p; unsigned int ifindex = 0; p.family = AF_INET6; p.prefix = dest.sin6.sin6_addr; if (flags & RTF_HOST) p.prefixlen = IPV6_MAX_PREFIXLEN; else p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);#ifdef KAME if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr)) { ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr); SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0); }#endif /* KAME */ if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); else rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0); }#endif /* HAVE_IPV6 */}/* Interface function for the kernel routing table updates. Support for RTM_CHANGE will be needed. */intrtm_write (int message, union sockunion *dest, union sockunion *mask, union sockunion *gate, unsigned int index, int zebra_flags, int metric){ int ret; caddr_t pnt; struct interface *ifp; struct sockaddr_in tmp_gate;#ifdef HAVE_IPV6 struct sockaddr_in6 tmp_gate6;#endif /* HAVE_IPV6 */ /* Sequencial number of routing message. */ static int msg_seq = 0; /* Struct of rt_msghdr and buffer for storing socket's data. */ struct { struct rt_msghdr rtm; char buf[512]; } msg; memset (&tmp_gate, 0, sizeof (struct sockaddr_in)); tmp_gate.sin_family = AF_INET;#ifdef HAVE_SIN_LEN tmp_gate.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */#ifdef HAVE_IPV6 memset (&tmp_gate6, 0, sizeof (struct sockaddr_in6)); tmp_gate6.sin6_family = AF_INET6;#ifdef SIN6_LEN tmp_gate6.sin6_len = sizeof (struct sockaddr_in6);#endif /* SIN6_LEN */#endif /* HAVE_IPV6 */ if (routing_sock < 0) return ZEBRA_ERR_EPERM; /* Clear and set rt_msghdr values */ memset (&msg, 0, sizeof (struct rt_msghdr)); msg.rtm.rtm_version = RTM_VERSION; msg.rtm.rtm_type = message; msg.rtm.rtm_seq = msg_seq++; msg.rtm.rtm_addrs = RTA_DST; msg.rtm.rtm_addrs |= RTA_GATEWAY; msg.rtm.rtm_flags = RTF_UP; msg.rtm.rtm_index = index; if (metric != 0) { msg.rtm.rtm_rmx.rmx_hopcount = metric; msg.rtm.rtm_inits |= RTV_HOPCOUNT; } ifp = if_lookup_by_index (index); if (gate && message == RTM_ADD) msg.rtm.rtm_flags |= RTF_GATEWAY; if (! gate && message == RTM_ADD && ifp && (ifp->flags & IFF_POINTOPOINT) == 0) msg.rtm.rtm_flags |= RTF_CLONING; /* If no protocol specific gateway is specified, use link address for gateway. */ if (! gate) { if (!ifp) { zlog_warn ("no gateway found for interface index %d", index); return -1; } gate = (union sockunion *) & ifp->sdl; } if (mask) msg.rtm.rtm_addrs |= RTA_NETMASK; else if (message == RTM_ADD) msg.rtm.rtm_flags |= RTF_HOST; /* Tagging route with flags */ msg.rtm.rtm_flags |= (RTF_PROTO1); /* Additional flags. */ if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) msg.rtm.rtm_flags |= RTF_BLACKHOLE;#ifdef HAVE_SIN_LEN#define SOCKADDRSET(X,R) \ if (msg.rtm.rtm_addrs & (R)) \ { \ int len = ROUNDUP ((X)->sa.sa_len); \ memcpy (pnt, (caddr_t)(X), len); \ pnt += len; \ }#else #define SOCKADDRSET(X,R) \ if (msg.rtm.rtm_addrs & (R)) \ { \ int len = ROUNDUP (sizeof((X)->sa)); \ memcpy (pnt, (caddr_t)(X), len); \ pnt += len; \ }#endif /* HAVE_SIN_LEN */ pnt = (caddr_t) msg.buf; /* Write each socket data into rtm message buffer */ SOCKADDRSET (dest, RTA_DST); SOCKADDRSET (gate, RTA_GATEWAY); SOCKADDRSET (mask, RTA_NETMASK); msg.rtm.rtm_msglen = pnt - (caddr_t) &msg; ret = write (routing_sock, &msg, msg.rtm.rtm_msglen); if (ret != msg.rtm.rtm_msglen) { if (errno == EEXIST) return ZEBRA_ERR_RTEXIST; if (errno == ENETUNREACH) return ZEBRA_ERR_RTUNREACH; zlog_warn ("write : %s (%d)", strerror (errno), errno); return -1; } return 0;}#include "thread.h"#include "zebra/zserv.h"extern struct thread_master *master;/* For debug purpose. */voidrtmsg_debug (struct rt_msghdr *rtm){ char *type = "Unknown"; struct message *mes; for (mes = rtm_type_str; mes->str; mes++) if (mes->key == rtm->rtm_type) { type = mes->str; break; } zlog_info ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, type); rtm_flag_dump (rtm->rtm_flags); zlog_info ("Kernel: message seq %d", rtm->rtm_seq); zlog_info ("Kernel: pid %d", rtm->rtm_pid);}/* This is pretty gross, better suggestions welcome -- mhandler */#ifndef RTAX_MAX#ifdef RTA_NUMBITS#define RTAX_MAX RTA_NUMBITS#else#define RTAX_MAX 8#endif /* RTA_NUMBITS */#endif /* RTAX_MAX *//* Kernel routing table and interface updates via routing socket. */intkernel_read (struct thread *thread){ int sock; int nbytes; struct rt_msghdr *rtm; union { /* Routing information. */ struct { struct rt_msghdr rtm; struct sockaddr addr[RTAX_MAX]; } r; /* Interface information. */ struct { struct if_msghdr ifm; struct sockaddr addr[RTAX_MAX]; } im; /* Interface address information. */ struct { struct ifa_msghdr ifa; struct sockaddr addr[RTAX_MAX]; } ia;#ifdef RTM_IFANNOUNCE /* Interface arrival/departure */ struct { struct if_announcemsghdr ifan; struct sockaddr addr[RTAX_MAX]; } ian;#endif /* RTM_IFANNOUNCE */ } buf; /* Fetch routing socket. */ sock = THREAD_FD (thread); nbytes= read (sock, &buf, sizeof buf); if (nbytes <= 0) { if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) zlog_warn ("routing socket error: %s", strerror (errno)); return 0; } thread_add_read (master, kernel_read, NULL, sock);#ifdef DEBUG rtmsg_debug (&buf.r.rtm);#endif /* DEBUG */ rtm = &buf.r.rtm; switch (rtm->rtm_type) { case RTM_ADD: case RTM_DELETE: rtm_read (rtm); break; case RTM_IFINFO: ifm_read (&buf.im.ifm); break; case RTM_NEWADDR: case RTM_DELADDR: ifam_read (&buf.ia.ifa); break;#ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: ifan_read (&buf.ian.ifan); break;#endif /* RTM_IFANNOUNCE */ default: break; } return 0;}/* Make routing socket. */voidrouting_socket (){ routing_sock = socket (AF_ROUTE, SOCK_RAW, 0); if (routing_sock < 0) { zlog_warn ("Can't init kernel routing socket"); return; } if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) zlog_warn ("Can't set O_NONBLOCK to routing socket"); /* kernel_read needs rewrite. */ thread_add_read (master, kernel_read, NULL, routing_sock);}/* Exported interface function. This function simply calls routing_socket (). */voidkernel_init (){ routing_socket ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -