📄 rsvp_trans.c
字号:
{ int status = SYS_NOERROR; /* Receive Multicast RSVP/UDP/IPv6 (Specified Interface) */ if (FAILED(drop_multicast_ipv6(fd6_pu,inf,g))) status = SYS_ERROR; if (!rawmode) { if (FAILED(drop_multicast_ipv6(fd6_pup,inf,g))) status = SYS_ERROR; } return(status);}#endif /* USE_IPV6 */#else /* IP_DSTOPTS *//* * These routines get complex for systems which cannot accept * ancillary data to sendmsg() to control the interface or vif to * use during the sending of a datagram in addition to router * alert options and hop limits. */static int nvifs = 0;static int port_pu,port_pup,pmax = 0;static int plist[NET_ADDR_SIZE][FD_SETSIZE];static int vlist[NET_ADDR_SIZE];static int ipproto_udp = IPPROTO_UDP;static int set_hop_limit(int fd,int proto,int opt,void *option,int size);static int set_router_alert(int fd,int proto,int opt,void *options,int size);static int set_interface_ipv4(net_addr_type type,net_if *inf);static int socket_send_udp_ipv4(int proto);#ifdef USE_IPV6static int set_interface_ipv6(net_addr_type type,net_if *inf);static int socket_send_udp_ipv6(int proto);#endif /* USE_IPV6 */#ifndef IP_PKTINFO/* * This function receives the packets using recvfrom(). */staticintreceive(int fd,net_addr *from,void *msg,int len,net_if *inf){ int n,sz; sz = sizeof(NET_GET_ADDR(from)); n = recvfrom(fd,msg,len,0, (struct sockaddr *) &NET_GET_ADDR(from),&sz); if (FAILED(n)) return(n); adjust(from,protocol_type[fd]); *inf = interface[fd]; return(n);}#endif /* IP_PKTINFO *//* * Specific outgoing network interface, source address, hop count, * and router alert option. This function returns the file * descriptor to use for the send operation. */staticintset_ancillary_data_ipv4(struct msghdr *hdr,net_addr_type type, struct sockaddr_in *to,struct sockaddr_in *from, void *msg,int len,net_if *inf,u_char hops,int ra){ int fd,opt,size; struct udphdr uh; static struct iovec iov[2]; struct sockaddr_in sin; static u_char ra_ipv4[4] = {148, 4, 0, 0}; if (inf != NULL) fd = set_interface_ipv4(type,inf); else fd = ulist[type]; if (FAILED(fd)) return(fd); if (to != NULL) { if (IN_IS_ADDR_MULTICAST(&to->sin_addr)) { opt = IP_MULTICAST_TTL;#ifdef SET_IP_TTL } else opt = IP_TTL;#endif /* SET_IP_TTL */ if (FAILED(set_hop_limit(fd,IPPROTO_IP,opt, &hops,sizeof(hops)))) return(SYS_ERROR);#ifndef SET_IP_TTL }#endif /* SET_IP_TTL */ } if (FAILED(set_router_alert(fd,IPPROTO_IP,IP_OPTIONS,ra_ipv4, (ra ? sizeof(ra_ipv4) : 0)))) return(SYS_ERROR); hdr->msg_iov = iov; if ((type == NET_ADDR_UDP_IPv4) && rawmode) { if (from != NULL) uh.uh_sport = from->sin_port; else { size = sizeof(sin); if (FAILED(getsockname(fd,(struct sockaddr *) &sin, &size))) uh.uh_sport = 0; else uh.uh_sport = sin.sin_port; } uh.uh_dport = to->sin_port; uh.uh_ulen = htons(len + sizeof(uh)); uh.uh_sum = htons(0); /* RSVP checksum is enough */ iov[0].iov_base = (void *) &uh; iov[0].iov_len = sizeof(uh); iov[1].iov_base = msg; iov[1].iov_len = len; hdr->msg_iovlen = 2; } else { iov[0].iov_base = msg; iov[0].iov_len = len; hdr->msg_iovlen = 1; } return(fd);}/* * We must create a RAW socket to send RSVP traffic on a per * phyical interface basis. This is due to the fact that the * socket can only be bound once and cannot to rebound to another * interface dynamically. This is also true for UDP/IP traffic. */staticintadd_if_ipv4(net_if *inf,struct in_addr *g){ int fd,status = SYS_NOERROR; struct in_addr in; struct sockaddr_in sin; in = NET_GET_ADDR_IPv4(&NET_GET_IF_PHY_ADDR(inf)); NET_SOCKADDR_IPv4(&sin,in); /* Send Raw RSVP/IPv4 to this Interface */ fd = socket_ipv4(SOCK_RAW,ipproto_rsvp,NET_ADDR_IPv4); if (FAILED(fd)) { if (rawmode) status = SYS_ERROR; } else { interface[fd] = *inf; if (FAILED(bind(fd,(struct sockaddr *) &sin,sizeof(sin)))) { net_error(NET_ERROR_SYSTEM,"bind"); failed(fd); fd = SYS_ERROR; status = SYS_ERROR; } /* Set to send raw multicast packet to this interface. * (Ignore errors on non-multicast interfaces) */ setsockopt(fd,IPPROTO_IP,IP_MULTICAST_IF, (char *) &in,sizeof(in)); } plist[NET_ADDR_IPv4][pmax] = fd; /* Receive Multicast RSVP/UDP/IPv4 on this interface */ if (FAILED(join_multicast_ipv4(fd_pu,inf,g))) status = SYS_ERROR; if (!rawmode) { if (FAILED(join_multicast_ipv4(fd_pup,inf,g))) status = SYS_ERROR; } /* Receive Unicast RSVP/UDP/IPv4 on this interface */ NET_SOCKADDR_UDP_IPv4(&sin,in,rawmode ? port_pu : port_pup); fd = socket_recv_udp_ipv4(&sin); if (FAILED(fd)) status = SYS_ERROR; else interface[fd] = *inf; if (rawmode) { /* Send RSVP/UDP/IPv4 on this interface */ fd = socket_send_udp_ipv4(ipproto_udp); if (FAILED(fd)) status = SYS_ERROR; else interface[fd] = *inf; } if (!FAILED(fd)) { /* Ignore errors on non-multicast interfaces */ setsockopt(fd,IPPROTO_IP,IP_MULTICAST_IF, (char *) &in,sizeof(in)); plist[NET_ADDR_UDP_IPv4][pmax++] = fd; } return(status);}staticintdel_if_ipv4(net_if *inf,struct in_addr *g){ /* FIX: Finish */ return(SYS_ERROR);}/* * We can create a RAW socket to listen for RSVP traffic on a per * vif basis. This will let us to determine on which vif a * datagram was received. */staticintadd_vif_ipv4(net_if *inf){ int fd;#ifdef IP_RSVP_VIF_ON int vif;#endif /* IP_RSVP_VIF_ON */ if (!rawmode) return(SYS_NOERROR); if (nvifs++ == 0) rsvp_off_ipv4(ulist[NET_ADDR_IPv4]); /* Receive RSVP/IPv4 (Specified VIF) */ fd = socket_ipv4(SOCK_RAW,ipproto_rsvp,NET_ADDR_IPv4); if (FAILED(fd)) return(fd);#ifdef IP_RSVP_VIF_ON vif = NET_GET_IF_VIF_ID(inf); if (FAILED(setsockopt(fd,IPPROTO_IP,IP_RSVP_VIF_ON, (char *) &vif,sizeof(vif)))) { net_error(NET_ERROR_SYSTEM,"IP_RSVP_VIF_ON"); return(failed(fd)); }#endif /* IP_RSVP_VIF_ON */ FD_SET(fd,&rset); interface[fd] = *inf; finalize[fd] = rsvp_vif_off_ipv4; return(SYS_NOERROR);}staticintdel_vif_ipv4(net_if *inf){ if (!rawmode) return(SYS_NOERROR); if (--nvifs == 0) rsvp_on_ipv4(ulist[NET_ADDR_IPv4]); /* FIX: Finish */ return(SYS_ERROR);}staticintrsvp_vif_off_ipv4(int fd){#ifdef IP_RSVP_VIF_OFF int vif; vif = NET_GET_IF_VIF_ID(&interface[fd]); if (FAILED(setsockopt(fd,IPPROTO_IP,IP_RSVP_VIF_OFF, (char *) &vif,sizeof(vif)))) { net_error(NET_ERROR_SYSTEM,"IP_RSVP_VIF_OFF"); return(SYS_ERROR); }#endif /* IP_RSVP_VIF_OFF */ return(SYS_NOERROR);}/* Sending a packet. Map inf to file descriptor and sets to * send multiast out specific interface. */staticintset_interface_ipv4(net_addr_type type, net_if *inf){ int i,fd,infn; net_addr *addr; struct in_addr in; switch(NET_GET_TYPE(inf)) { case NET_IF_PHY: if (NET_GET_TYPE(&NET_GET_IF_PHY_ADDR(inf)) != NET_ADDR_IPv4) return(SYS_ERROR); for (i = 0;i < pmax; i++) { fd = plist[type][i]; if (FAILED(fd)) continue; if (net_if_equal(inf,&interface[fd])) return(fd); } return(SYS_ERROR); case NET_IF_VIF: addr = &NET_GET_IF_VIF_ADDR(inf); if (NET_GET_TYPE(addr) != NET_ADDR_IPv4) return(SYS_ERROR); in = NET_GET_ADDR_IPv4(addr); fd = vlist[type]; if (FAILED(setsockopt(fd,IPPROTO_IP,IP_MULTICAST_IF, (char *) &in,sizeof(in)))) { net_error(NET_ERROR_SYSTEM,"IP_MULTICAST_IF"); return(SYS_ERROR); }#ifdef SOLARIS infn = 1; if (FAILED(setsockopt(fd,SOL_SOCKET,SO_DONTROUTE, (char *) &infn,sizeof(infn)))) { net_error(NET_ERROR_SYSTEM,"SO_DONTROUTE"); return(failed(fd)); }#else /* SOLARIS */ infn = NET_GET_IF_VIF_ID(inf);#ifndef linux if (FAILED(setsockopt(fd,IPPROTO_IP,IP_MULTICAST_VIF, (char *) &infn,sizeof(infn)))) { net_error(NET_ERROR_SYSTEM,"IP_MULTICAST_VIF"); return(SYS_ERROR); }#endif /* linux */#endif /* SOLARIS */ return(fd); default: return(SYS_ERROR); }}staticintsocket_send_udp_ipv4(int proto){ if (rawmode) return(socket_ipv4(SOCK_RAW,proto,NET_ADDR_UDP_IPv4)); return(socket_ipv4(SOCK_DGRAM,PF_UNSPEC,NET_ADDR_UDP_IPv4));}/* * Sending datagrams on physical interfaces and virtual interfaces * is handled by differing interfaces. Create a socket for * sending on any virtual interface. Sockets for sending on a * physical interface will be done on a per interface basis * below. */staticint#ifdef USE_IPV6initialize(int pu,int pup,struct in_addr *g,struct in6_addr *g6)#else /* USE_IPV6 */initialize(int pu,int pup,struct in_addr *g)#endif /* USE_IPV6 */{ int fd,status = SYS_NOERROR; struct protoent *p; p = getprotobyname("udp"); if (p != NULL) ipproto_udp = p->p_proto; port_pu = pu; port_pup = pup; for (fd = 0;fd < FD_SETSIZE; fd++) interface[fd] = unknown; /* Send RSVP/UDP/IPv4 (Any Interface) */ if (rawmode) { fd = socket_send_udp_ipv4(ipproto_udp); if (FAILED(fd)) status = SYS_ERROR; ulist[NET_ADDR_UDP_IPv4] = fd; } /* Send RSVP/IPv4 (Specified VIF) */ fd = socket_ipv4(SOCK_RAW,ipproto_rsvp,NET_ADDR_IPv4); if (rawmode && FAILED(fd)) status = SYS_ERROR; vlist[NET_ADDR_IPv4] = fd; /* Send RSVP/UDP/IPv4 (Specified VIF) */ fd = socket_send_udp_ipv4(ipproto_udp); vlist[NET_ADDR_UDP_IPv4] = fd; if (FAILED(fd)) status = SYS_ERROR;#ifdef USE_IPV6 /* Send RSVP/UDP/IPv6 (Any Interface) */ if (rawmode) { fd = socket_send_udp_ipv6(ipproto_udp); if (FAILED(fd)) status = SYS_ERROR; ulist[NET_ADDR_UDP_IPv6] = fd; } /* Send RSVP/IPv6 (Specified VIF) */ fd = socket_ipv6(SOCK_RAW,ipproto_rsvp,NET_ADDR_IPv6); if (rawmode && FAILED(fd)) status = SYS_ERROR; vlist[NET_ADDR_IPv6] = fd; /* Send RSVP/UDP/IPv6 (Specified VIF) */ fd = socket_send_udp_ipv6(ipproto_udp); vlist[NET_ADDR_UDP_IPv6] = fd; if (FAILED(fd)) status = SYS_ERROR;#endif /* USE_IPV6 */ return(status);}/* * Set the maximum hop limit. Once set, it remains set until it * is turned off. */staticintset_hop_limit(int fd,int proto,int opt,void *option,int size){ if (FAILED(setsockopt(fd,proto,opt,option,size))) { net_error(NET_ERROR_SYSTEM,"hop count"); return(SYS_ERROR); } return(SYS_NOERROR);}/* * Set the Router Alert Option. Once set, it remains set until it * is turned off. */staticintset_router_alert(int fd,int proto,int opt,void *options,int size){ if (FAILED(setsockopt(fd,proto,opt,options,size))) { net_error(NET_ERROR_SYSTEM,"Router alert"); return(SYS_ERROR); } return(SYS_NOERROR);}#ifdef USE_IPV6staticintset_ancillary_data_ipv6(struct msghdr *hdr,net_addr_type type, struct sockaddr_in6 *to,struct sockaddr_in6 *from, void *msg,int len,net_if *inf,u_char hops,int ra){ int fd,ihops = hops; static struct iovec iov[2]; if (inf != NULL) fd = set_interface_ipv6(type,inf); else fd = ulist[type]; if (FAILED(fd)) return(fd); if (to != NULL) { if (FAILED(set_hop_limit(fd,IPPROTO_IPV6, (IN6_IS_ADDR_MULTICAST(&to->sin6_addr) ? IPV6_MULTICAST_HOPS : IPV6_UNICAST_HOPS), &ihops,sizeof(ihops)))) {#ifndef WORKAROUNDS return(SYS_ERROR);#endif /* WORKAROUNDS */ } } /* FIX: v6 router alert */ hdr->msg_iov = iov; /* FIX: v6 udp header *//* if ((type == NET_ADDR_UDP_IPv6) && rawmode) { return(SYS_ERROR); } else {*/ iov[0].iov_base = msg; iov[0].iov_len = len; hdr->msg_iovlen = 1;/* }*/ return(fd);}staticintadd_if_ipv6(net_if *inf,struct in6_addr *g){ int fd,status = SYS_NOERROR; unsigned int index; struct in6_addr in; struct sockaddr_in6 sin; in = NET_GET_ADDR_IPv6(&NET_GET_IF_PHY_ADDR(inf)); NET_SOCKADDR_IPv6(&sin,in); /* Send RSVP/IPv6 (Specified Interface) */ fd = socket_ipv6(SOCK_RAW,ipproto_rsvp,NET_ADDR_IPv6); if (FAILED(fd)) { if (rawmode) status = SYS_ERROR; } else { interface[fd] = *inf; if (FAILED(bind(fd,(struct sockaddr *) &sin,sizeof(sin)))) {#ifndef WORKAROUNDS net_error(NET_ERROR_SYSTEM,"bind"); failed(fd); fd = SYS_ERROR; status = SYS_ERROR;#endif /* WORKAROUNDS */ } index = NET_GET_IF_PHY_ID(inf); /* Ignore errors on non-multicast interfaces */ setsockopt(fd,IPPROTO_IPV6,IPV6_MULTICAST_IF, (char *) &index,sizeof(index)); } plist[NET_ADDR_IPv6][pmax] = fd; /* Receive Multicast RSVP/UDP/IPv6 (Specified Interface) */ if (FAILED(join_multicast_ipv6(fd6_pu,inf,g))) status = SYS_ERROR; if (!rawmode) { if (FAILED(join_multicast_ipv6(fd6_pup,inf,g))) status = SYS_ERROR; } /* Receive Unicast RSVP/UDP/IPv6 (Specified Interface) */ NET_SOCKADDR_UDP_IPv6(&sin,in,rawmode ? port_pu : port_pup); fd = socket_recv_udp_ipv6(&sin); if (FAILED(fd)) status = SYS_ERROR; else interface[fd] = *inf;/* if (rawmode) {*/ /* Send RSVP/UDP/IPv6 (Specified Interface) *//* fd = socket_send_udp_ipv6(ipproto_udp); if (FAILED(fd)) status = SYS_ERROR; else interface[fd] = *inf; }*/ plist[NET_ADDR_UDP_IPv6][pmax++] = fd; index = NET_GET_IF_PHY_ID(inf); /* Ignore errors on non-multicast interfaces */ setsockopt(fd,IPPROTO_IPV6,IPV6_MULTICAST_IF, (char *) &index,sizeof(index)); return(status);}staticintdel_if_ipv6(net_if *inf,struct in6_addr *g){ /* FIX: Finish */ return(SYS_ERROR);}staticintset_interface_ipv6(net_addr_type type,net_if *inf){ int i,fd; switch(NET_GET_TYPE(inf)) { case NET_IF_PHY: if (NET_GET_TYPE(&NET_GET_IF_PHY_ADDR(inf)) != NET_ADDR_IPv6) return(SYS_ERROR); for (i = 0;i < pmax; i++) { fd = plist[type][i]; if (FAILED(fd)) continue; if (net_if_equal(inf,&interface[fd])) return(fd); } return(SYS_ERROR); default: return(SYS_ERROR); }}staticintsocket_send_udp_ipv6(int proto){ /* FIX: v6 udp header *//* if (rawmode) return(socket_ipv6(SOCK_RAW,proto,NET_ADDR_UDP_IPv6));*/ return(socket_ipv6(SOCK_DGRAM,PF_UNSPEC,NET_ADDR_UDP_IPv6));}#endif /* USE_IPV6 */#endif /* IP_DSTOPTS *//* Print out active file descriptors */void fds_print(FILE *fo, char *title) { int fd, type = 0; const char *inf_str, *net_if_print(const net_if *); char *netif_type_name[] = {"unk", "PHY", "VIF", "ID ", "STR"}; char *netaddr_type_name[] = {"Raw IPv4", "UDP IPv4", "Raw IPv6", "UDP IPv6"}; if (fo == NULL) return; fprintf(fo, "Network File Descriptors: %s\n", title); for (fd = 0;fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd, &fset)) { inf_str = net_if_print(&interface[fd]); fprintf(fo, "fd=%d net_ifType=%s Inf=%s", fd, netif_type_name[protocol_type[fd]], inf_str); if (fd == fd_pu) fprintf(fo, " UDP Pu"); if (fd == fd_pup) fprintf(fo, " UDP Pu'"); if (FD_ISSET(fd, &rset)) fprintf(fo, " RECV"); #if !defined(IP_DSTOPTS) for (type=0; type < NET_ADDR_SIZE; type++) { int i; for (i=0; i < pmax; i++) { if (fd == plist[type][i]) fprintf(fo, " SEND %s", netaddr_type_name[type]); } if (fd == vlist[type]) fprintf(fo, " VIF Addr %s", netaddr_type_name[type]); }#endif /* IP_DSTOPTS */ fprintf(fo, "\n"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -