/* * Do option processing on a datagram, possibly discarding it if bad options * are encountered, or forwarding it if source-routed. * * The pass argument is used when operating in the IPSTEALTH mode to tell * what options to process: [LS]SRR (pass 0) or the others (pass 1). The * reason for as many as two passes is that when doing IPSTEALTH, non-routing * options should be processed only if the packet is for us. * * Returns 1 if packet has been forwarded/freed, 0 if the packet should be * processed further. */ int ip_dooptions(struct mbuf *m, int pass) { struct ip *ip = mtod(m, struct ip *); u_char *cp; struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; uint32_t ntime; struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; /* Ignore or reject packets with IP options. */ if (ip_doopts == 0) return 0; else if (ip_doopts == 2) { type = ICMP_UNREACH; code = ICMP_UNREACH_FILTER_PROHIB; goto bad; } dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { if (cnt < IPOPT_OLEN + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } optlen = cp[IPOPT_OLEN]; if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } } switch (opt) { default: break; /* * Source routing with record. Find interface with current * destination address. If none on this machine then drop if * strictly routed, or do nothing if loosely routed. Record * interface address and bring up next address component. If * strictly routed make sure next address is on directly * accessible net. */ case IPOPT_LSRR: case IPOPT_SSRR: #ifdef IPSTEALTH if (V_ipstealth && pass > 0) break; #endif if (optlen < IPOPT_OFFSET + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = ip->ip_dst; if (ifa_ifwithaddr_check((struct sockaddr *)&ipaddr) == 0) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } if (!ip_dosourceroute) goto nosourcerouting; /* * Loose routing, and not at next destination * yet; nothing to do except forward. */ break; } off--; /* 0 origin */ if (off > optlen - (int)sizeof(struct in_addr)) { /* * End of source route. Should be for us. */ if (!ip_acceptsourceroute) goto nosourcerouting; save_rte(m, cp, ip->ip_src); break; } #ifdef IPSTEALTH if (V_ipstealth) goto dropit; #endif if (!ip_dosourceroute) { if (V_ipforwarding) { char buf[16]; /* aaa.bbb.ccc.ddd\0 */ /* * Acting as a router, so generate * ICMP */ nosourcerouting: strcpy(buf, inet_ntoa(ip->ip_dst)); log(LOG_WARNING, "attempted source route from %s to %s\n", inet_ntoa(ip->ip_src), buf); type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } else { /* * Not acting as a router, so * silently drop. */ #ifdef IPSTEALTH dropit: #endif IPSTAT_INC(ips_cantforward); m_freem(m); return (1); } } /* * locate outgoing interface */ (void)memcpy(&ipaddr.sin_addr, cp + off, sizeof(ipaddr.sin_addr)); if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * #define SA struct sockaddr * if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == NULL) ia = (INA)ifa_ifwithnet((SA)&ipaddr, 0); } else /* XXX MRT 0 for routing */ ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m)); if (ia == NULL) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } ip->ip_dst = ipaddr.sin_addr; (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); ifa_free(&ia->ia_ifa); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Let ip_intr's mcast routing check handle mcast pkts */ forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); break; case IPOPT_RR: #ifdef IPSTEALTH if (V_ipstealth && pass == 0) break; #endif if (optlen < IPOPT_OFFSET + sizeof(*cp)) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } /* * If no space remains, ignore. */ off--; /* 0 origin */ if (off > optlen - (int)sizeof(struct in_addr)) break; (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst, sizeof(ipaddr.sin_addr)); /* * Locate outgoing interface; if we're the * destination, use the incoming interface (should be * same). */ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == NULL && (ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m))) == NULL) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; } (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); ifa_free(&ia->ia_ifa); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS: #ifdef IPSTEALTH if (V_ipstealth && pass == 0) break; #endif code = cp - (u_char *)ip; if (optlen < 4 || optlen > 40) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } if ((off = cp[IPOPT_OFFSET]) < 5) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } if (off > optlen - (int)sizeof(int32_t)) { cp[IPOPT_OFFSET + 1] += (1 << 4); if ((cp[IPOPT_OFFSET + 1] & 0xf0) == 0) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } break; } off--; /* 0 origin */ sin = (struct in_addr *)(cp + off); switch (cp[IPOPT_OFFSET + 1] & 0x0f) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: if (off + sizeof(uint32_t) + sizeof(struct in_addr) > optlen) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = dst; ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, m->m_pkthdr.rcvif); if (ia == NULL) continue; (void)memcpy(sin, &IA_SIN(ia)->sin_addr, sizeof(struct in_addr)); ifa_free(&ia->ia_ifa); cp[IPOPT_OFFSET] += sizeof(struct in_addr); off += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: if (off + sizeof(uint32_t) + sizeof(struct in_addr) > optlen) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } (void)memcpy(&ipaddr.sin_addr, sin, sizeof(struct in_addr)); if (ifa_ifwithaddr_check((SA)&ipaddr) == 0) continue; cp[IPOPT_OFFSET] += sizeof(struct in_addr); off += sizeof(struct in_addr); break; default: code = &cp[IPOPT_OFFSET + 1] - (u_char *)ip; goto bad; } ntime = iptime(); (void)memcpy(cp + off, &ntime, sizeof(uint32_t)); cp[IPOPT_OFFSET] += sizeof(uint32_t); } } if (forward && V_ipforwarding) { ip_forward(m, 1); return (1); } return (0); bad: icmp_error(m, type, code, 0, 0); IPSTAT_INC(ips_badoptions); return (1); }
/* Dies on error */ static void parse_args(char **argv, int cmd, struct ip_tunnel_parm *p) { static const char keywords[] ALIGN1 = "mode\0""ipip\0""ip/ip\0""gre\0""gre/ip\0""sit\0""ipv6/ip\0" "key\0""ikey\0""okey\0""seq\0""iseq\0""oseq\0" "csum\0""icsum\0""ocsum\0""nopmtudisc\0""pmtudisc\0" "remote\0""any\0""local\0""dev\0" "ttl\0""inherit\0""tos\0""dsfield\0" "name\0"; enum { ARG_mode, ARG_ipip, ARG_ip_ip, ARG_gre, ARG_gre_ip, ARG_sit, ARG_ip6_ip, ARG_key, ARG_ikey, ARG_okey, ARG_seq, ARG_iseq, ARG_oseq, ARG_csum, ARG_icsum, ARG_ocsum, ARG_nopmtudisc, ARG_pmtudisc, ARG_remote, ARG_any, ARG_local, ARG_dev, ARG_ttl, ARG_inherit, ARG_tos, ARG_dsfield, ARG_name }; int count = 0; char medium[IFNAMSIZ]; int key; memset(p, 0, sizeof(*p)); medium[0] = '\0'; p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (*argv) { key = index_in_strings(keywords, *argv); if (key == ARG_mode) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key == ARG_ipip || key == ARG_ip_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_IPIP; } else if (key == ARG_gre || key == ARG_gre_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_GRE; } else if (key == ARG_sit || key == ARG_ip6_ip) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { bb_error_msg_and_die("%s tunnel mode", "you managed to ask for more than one"); } p->iph.protocol = IPPROTO_IPV6; } else { bb_error_msg_and_die("%s tunnel mode", "cannot guess"); } } else if (key == ARG_key) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "key"); p->i_key = p->o_key = htonl(uval); } } else if (key == ARG_ikey) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "ikey"); p->i_key = htonl(uval); } } else if (key == ARG_okey) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { uval = get_unsigned(*argv, "okey"); p->o_key = htonl(uval); } } else if (key == ARG_seq) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (key == ARG_iseq) { p->i_flags |= GRE_SEQ; } else if (key == ARG_oseq) { p->o_flags |= GRE_SEQ; } else if (key == ARG_csum) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (key == ARG_icsum) { p->i_flags |= GRE_CSUM; } else if (key == ARG_ocsum) { p->o_flags |= GRE_CSUM; } else if (key == ARG_nopmtudisc) { p->iph.frag_off = 0; } else if (key == ARG_pmtudisc) { p->iph.frag_off = htons(IP_DF); } else if (key == ARG_remote) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_any) p->iph.daddr = get_addr32(*argv); } else if (key == ARG_local) { NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_any) p->iph.saddr = get_addr32(*argv); } else if (key == ARG_dev) { NEXT_ARG(); strncpy_IFNAMSIZ(medium, *argv); } else if (key == ARG_ttl) { unsigned uval; NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_inherit) { uval = get_unsigned(*argv, "TTL"); if (uval > 255) invarg(*argv, "TTL must be <=255"); p->iph.ttl = uval; } } else if (key == ARG_tos || key == ARG_dsfield) { uint32_t uval; NEXT_ARG(); key = index_in_strings(keywords, *argv); if (key != ARG_inherit) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg(*argv, "TOS"); p->iph.tos = uval; } else p->iph.tos = 1; } else { if (key == ARG_name) { NEXT_ARG(); } if (p->name[0]) duparg2("name", *argv); strncpy_IFNAMSIZ(p->name, *argv); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (do_get_ioctl(*argv, &old_p)) exit(EXIT_FAILURE); *p = old_p; } } count++; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; } if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { bb_error_msg_and_die("keys are not allowed with ipip and sit"); } } if (medium[0]) { p->link = do_ioctl_get_ifindex(medium); } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { bb_error_msg_and_die("broadcast tunnel requires a source address"); } }
/* * Do what we need to do when inserting a route. */ static struct radix_node * in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, struct radix_node *treenodes) { struct rtentry *rt = (struct rtentry *)treenodes; struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt); struct radix_node *ret; /* * For IP, all unicast non-host routes are automatically cloning. */ if(IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) rt->rt_flags |= RTF_MULTICAST; if(!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) { rt->rt_flags |= RTF_PRCLONING; } /* * A little bit of help for both IP output and input: * For host routes, we make sure that RTF_BROADCAST * is set for anything that looks like a broadcast address. * This way, we can avoid an expensive call to in_broadcast() * in ip_output() most of the time (because the route passed * to ip_output() is almost always a host route). * * We also do the same for local addresses, with the thought * that this might one day be used to speed up ip_input(). * * We also mark routes to multicast addresses as such, because * it's easy to do and might be useful (but this is much more * dubious since it's so easy to inspect the address). (This * is done above.) */ if (rt->rt_flags & RTF_HOST) { if (in_broadcast(sin->sin_addr, rt->rt_ifp)) { rt->rt_flags |= RTF_BROADCAST; } else { #define satosin(sa) ((struct sockaddr_in *)sa) if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr == sin->sin_addr.s_addr) rt->rt_flags |= RTF_LOCAL; #undef satosin } } if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) && rt->rt_ifp) rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; ret = rn_addroute(v_arg, n_arg, head, treenodes); if (ret == NULL && rt->rt_flags & RTF_HOST) { struct rtentry *rt2; /* * We are trying to add a host route, but can't. * Find out if it is because of an * ARP entry and delete it if so. */ rt2 = rtalloc1((struct sockaddr *)sin, 0, RTF_CLONING | RTF_PRCLONING); if (rt2) { if (rt2->rt_flags & RTF_LLINFO && rt2->rt_flags & RTF_HOST && rt2->rt_gateway && rt2->rt_gateway->sa_family == AF_LINK) { rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt2), rt2->rt_gateway, rt_mask(rt2), rt2->rt_flags, 0); ret = rn_addroute(v_arg, n_arg, head, treenodes); } RTFREE(rt2); } } return ret; }
int in_pcbladdr(struct inpcb *inp, struct mbuf *nam, struct sockaddr_in **plocal_sin) { struct in_ifaddr *ia; register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) return (EINVAL); if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); if (sin->sin_port == 0) return (EADDRNOTAVAIL); if (in_ifaddr) { /* * If the destination address is INADDR_ANY, * use the primary local address. * If the supplied address is INADDR_BROADCAST, * and the primary interface supports broadcast, * choose the broadcast address for that interface. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) #define sintosa(sin) ((struct sockaddr *)(sin)) #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) if (sin->sin_addr.s_addr == INADDR_ANY) sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr; else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST && (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST)) sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr; } if (inp->inp_laddr.s_addr == INADDR_ANY) { register struct route *ro; ia = (struct in_ifaddr *)0; /* * If route is known or can be allocated now, * our src addr is taken from the i/f, else punt. */ ro = &inp->inp_route; if (ro->ro_rt && (satosin(&ro->ro_dst)->sin_addr.s_addr != sin->sin_addr.s_addr || inp->inp_socket->so_options & SO_DONTROUTE)) { RTFREE(ro->ro_rt); ro->ro_rt = (struct rtentry *)0; } if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || ro->ro_rt->rt_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(struct sockaddr_in); ((struct sockaddr_in *) &ro->ro_dst)->sin_addr = sin->sin_addr; rtalloc(ro); } /* * If we found a route, use the address * corresponding to the outgoing interface * unless it is the loopback (in case a route * to our address on another net goes to loopback). */ if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) ia = ifatoia(ro->ro_rt->rt_ifa); if (ia == 0) { u_short fport = sin->sin_port; sin->sin_port = 0; ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin))); if (ia == 0) ia = ifatoia(ifa_ifwithnet(sintosa(sin))); sin->sin_port = fport; if (ia == 0) ia = in_ifaddr; if (ia == 0) return (EADDRNOTAVAIL); } /* * If the destination address is multicast and an outgoing * interface has been set as a multicast option, use the * address of that interface as our source address. */ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) && inp->inp_moptions != NULL) { struct ip_moptions *imo; struct ifnet *ifp; imo = inp->inp_moptions; if (imo->imo_multicast_ifp != NULL) { ifp = imo->imo_multicast_ifp; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; if (ia == 0) return (EADDRNOTAVAIL); } } /* * Don't do pcblookup call here; return interface in plocal_sin * and exit to caller, that will do the lookup. */ *plocal_sin = &ia->ia_addr; } return(0); }
static int get_mcast_options(int argc, char **argv, int i) { char *address = XDM_DEFAULT_MCAST_ADDR6; int hopcount = 1; struct addrinfo hints; char portstr[6]; int gaierr; struct addrinfo *ai, *firstai; if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { address = argv[i++]; if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { hopcount = strtol(argv[i++], NULL, 10); if ((hopcount < 1) || (hopcount > 255)) { FatalError("Xserver: multicast hop count out of range: %d\n", hopcount); } } } if (xdm_udp_port > 0 && xdm_udp_port < 65535) { sprintf(portstr, "%d", xdm_udp_port); } else { FatalError("Xserver: port out of range: %d\n", xdm_udp_port); } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) { for (ai = firstai; ai != NULL; ai = ai->ai_next) { if (((ai->ai_family == AF_INET) && IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr) ->sin_addr.s_addr)) || ((ai->ai_family == AF_INET6) && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr) ->sin6_addr))) break; } if (ai == NULL) { FatalError ("Xserver: address not supported multicast type %s\n", address); } else { struct multicastinfo *mcastinfo, *mcl; mcastinfo = malloc(sizeof(struct multicastinfo)); mcastinfo->next = NULL; mcastinfo->ai = firstai; mcastinfo->hops = hopcount; if (mcastlist == NULL) { mcastlist = mcastinfo; } else { for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) { /* Do nothing - just find end of list */ } mcl->next = mcastinfo; } } } else { FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address); } return i; }
void handle_igmpv3_toin( __u32 group, __u32 src, int srcnum, __u32 *grec_src ) { struct mcft_entry *mymcp; if(!IN_MULTICAST(group)) return; /* check if it's protocol reserved group */ if((group&0xFFFFFF00)==0xE0000000) return; if(!chk_mcft(group)) { mymcp = add_mcft(group, src); if(!mymcp) return; mymcp->igmp_ver = IGMP_VER_3; igmp_add_group( group ); } mymcp = get_mcft(group); if(mymcp) { switch( mymcp->filter_mode ) { case MCAST_INCLUDE: { int i; struct src_entry *s, *old_set; // Mason Yu Test //printf("handle_igmpv3_toin: MCAST_INCLUDE\n"); #ifdef KEEP_GROUP_MEMBER if ( srcnum != 0 ){ add_user(mymcp, src); } #endif //IN(A), TO_IN(B) => IN(A+B) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { if( check_src_set( grec_src[i], old_set )==0 ) igmp_add_mr( mymcp->grp_addr, grec_src[i], 1 ); s = add_to_srclist( mymcp, grec_src[i] ); if(s) { // (B)= GMI s->timer.lefttime = MEMBER_QUERY_INTERVAL; s->timer.retry_left = MEMBER_QUERY_COUNT; } } //send Q(G,A-B) i=0; s = old_set; while(s) { if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { gsrctmp[i]=s->srcaddr; /*lower A-B timer to LMQT*/ s->timer.lefttime=LAST_MEMBER_QUERY_INTERVAL; s->timer.retry_left=LAST_MEMBER_QUERY_COUNT; i++; if(i==IGMPV3_MAX_SRCNUM) break; } s = s->next; } if(i>0) igmpv3_query( mymcp, i, gsrctmp ); //set the new state mymcp->filter_mode = MCAST_INCLUDE; igmp_set_srcfilter( mymcp ); #ifdef KEEP_GROUP_MEMBER if ( srcnum == 0 ) { int count; count = del_user(mymcp, src); if (count == 0) {// no member, drop it! del_mr(mymcp->grp_addr); del_mcft(mymcp->grp_addr); } } #endif } break; case MCAST_EXCLUDE: { int i; struct src_entry *s, *old_set; // Mason Yu Test //printf("handle_igmpv3_toin: MCAST_EXCLUDE and srcnum=%d\n", srcnum); #ifdef KEEP_GROUP_MEMBER if ( srcnum != 0 ){ add_user(mymcp, src); } #endif //EX(X,Y), TO_IN(A) => EX(X+A, Y-A) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { s = add_to_srclist( mymcp, grec_src[i] ); if(s) { // (A)= GMI s->timer.lefttime = MEMBER_QUERY_INTERVAL; s->timer.retry_left = MEMBER_QUERY_COUNT; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 1 ); } } //send Q(G,X-A) i=0; s = old_set; while(s) { if( s->timer.lefttime>0 ) { if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { gsrctmp[i]=s->srcaddr; /*lower X-A timer to LMQT*/ s->timer.lefttime=LAST_MEMBER_QUERY_INTERVAL; s->timer.retry_left=LAST_MEMBER_QUERY_COUNT; i++; if(i==IGMPV3_MAX_SRCNUM) break; } } s = s->next; } if(i>0) igmpv3_query( mymcp, i, gsrctmp ); /* lower group filter timer to LMQT*/ mymcp->timer.lefttime=LAST_MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left=LAST_MEMBER_QUERY_COUNT; //send Q(G) if( mymcp->igmp_ver==IGMP_VER_3 ) igmpv3_query( mymcp, 0, NULL ); else igmp_query(ALL_SYSTEMS, mymcp->grp_addr, LAST_MEMBER_QUERY_INTERVAL); //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); #ifdef KEEP_GROUP_MEMBER if ( srcnum == 0 ) { int count; count = del_user(mymcp, src); if (count == 0) {// no member, drop it! del_mr(mymcp->grp_addr); del_mcft(mymcp->grp_addr); } } #endif } break; default: break; } } }
/** * Adds a specified route to the routingtable. * If the route already exists, the existing route * is updated... */ int insertRoute(uint32_t group, int ifx) { struct Config *conf = getCommonConfig(); struct RouteTable* croute; // Sanitycheck the group adress... if( ! IN_MULTICAST( ntohl(group) )) { my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group. Table insert failed.", inetFmt(group, s1)); return 0; } // Santiycheck the VIF index... //if(ifx < 0 || ifx >= MAX_MC_VIFS) { if(ifx >= MAX_MC_VIFS) { my_log(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.",ifx,MAX_MC_VIFS); return 0; } // Try to find an existing route for this group... croute = findRoute(group); if(croute==NULL) { struct RouteTable* newroute; my_log(LOG_DEBUG, 0, "No existing route for %s. Create new.", inetFmt(group, s1)); // Create and initialize the new route table entry.. newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable)); // Insert the route desc and clear all pointers... newroute->group = group; memset(newroute->originAddrs, 0, MAX_ORIGINS * sizeof(newroute->originAddrs[0])); newroute->nextroute = NULL; newroute->prevroute = NULL; // The group is not joined initially. newroute->upstrState = ROUTESTATE_NOTJOINED; // The route is not active yet, so the age is unimportant. newroute->ageValue = conf->robustnessValue; newroute->ageActivity = 0; BIT_ZERO(newroute->ageVifBits); // Initially we assume no listeners. // Set the listener flag... BIT_ZERO(newroute->vifBits); // Initially no listeners... if(ifx >= 0) { BIT_SET(newroute->vifBits, ifx); } // Check if there is a table already.... if(routing_table == NULL) { // No location set, so insert in on the table top. routing_table = newroute; my_log(LOG_DEBUG, 0, "No routes in table. Insert at beginning."); } else { my_log(LOG_DEBUG, 0, "Found existing routes. Find insert location."); // Check if the route could be inserted at the beginning... if(routing_table->group > group) { my_log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1)); // Insert at beginning... newroute->nextroute = routing_table; newroute->prevroute = NULL; routing_table = newroute; // If the route has a next node, the previous pointer must be updated. if(newroute->nextroute != NULL) { newroute->nextroute->prevroute = newroute; } } else { // Find the location which is closest to the route. for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) { // Find insert position. if(croute->nextroute->group > group) { break; } } my_log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1)); // Insert after current... newroute->nextroute = croute->nextroute; newroute->prevroute = croute; if(croute->nextroute != NULL) { croute->nextroute->prevroute = newroute; } croute->nextroute = newroute; } } // Set the new route as the current... croute = newroute; // Log the cleanup in debugmode... my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d", inetFmt(croute->group, s1),ifx); } else if(ifx >= 0) { // The route exists already, so just update it. BIT_SET(croute->vifBits, ifx); // Register the VIF activity for the aging routine BIT_SET(croute->ageVifBits, ifx); // Log the cleanup in debugmode... my_log(LOG_INFO, 0, "Updated route entry for %s on VIF #%d", inetFmt(croute->group, s1), ifx); // Update route in kernel... if(!internUpdateKernelRoute(croute, 1)) { my_log(LOG_WARNING, 0, "The insertion into Kernel failed."); return 0; } } // Send join message upstream, if the route has no joined flag... if(croute->upstrState != ROUTESTATE_JOINED) { // Send Join request upstream sendJoinLeaveUpstream(croute, 1); } logRouteTable("Insert Route"); return 1; }
static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */ size_t *ret_sockets_num, const char *node, const char *service, int listen) { struct addrinfo ai_hints; struct addrinfo *ai_list; struct addrinfo *ai_ptr; int ai_return; socket_entry_t *sockets = NULL; size_t sockets_num = 0; int status; if (*ret_sockets != NULL) return (EINVAL); memset (&ai_hints, 0, sizeof (ai_hints)); ai_hints.ai_flags = 0; #ifdef AI_PASSIVE ai_hints.ai_flags |= AI_PASSIVE; #endif #ifdef AI_ADDRCONFIG ai_hints.ai_flags |= AI_ADDRCONFIG; #endif ai_hints.ai_family = AF_UNSPEC; ai_hints.ai_socktype = SOCK_DGRAM; ai_hints.ai_protocol = IPPROTO_UDP; ai_return = getaddrinfo (node, service, &ai_hints, &ai_list); if (ai_return != 0) { char errbuf[1024]; ERROR ("gmond plugin: getaddrinfo (%s, %s) failed: %s", (node == NULL) ? "(null)" : node, (service == NULL) ? "(null)" : service, (ai_return == EAI_SYSTEM) ? sstrerror (errno, errbuf, sizeof (errbuf)) : gai_strerror (ai_return)); return (-1); } for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */ { socket_entry_t *tmp; tmp = realloc (sockets, (sockets_num + 1) * sizeof (*sockets)); if (tmp == NULL) { ERROR ("gmond plugin: realloc failed."); continue; } sockets = tmp; sockets[sockets_num].fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); if (sockets[sockets_num].fd < 0) { char errbuf[1024]; ERROR ("gmond plugin: socket failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); continue; } assert (sizeof (sockets[sockets_num].addr) >= ai_ptr->ai_addrlen); memcpy (&sockets[sockets_num].addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen); sockets[sockets_num].addrlen = ai_ptr->ai_addrlen; /* Sending socket: Open only one socket and don't bind it. */ if (listen == 0) { sockets_num++; break; } else { int yes = 1; setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof (yes)); } status = bind (sockets[sockets_num].fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); if (status != 0) { char errbuf[1024]; ERROR ("gmond plugin: bind failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); close (sockets[sockets_num].fd); continue; } if (ai_ptr->ai_family == AF_INET) { struct sockaddr_in *addr; struct ip_mreq mreq; int loop; addr = (struct sockaddr_in *) ai_ptr->ai_addr; if (!IN_MULTICAST (ntohl (addr->sin_addr.s_addr))) { sockets_num++; continue; } loop = 1; setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *) &loop, sizeof (loop)); memset (&mreq, 0, sizeof (mreq)); mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr; mreq.imr_interface.s_addr = htonl (INADDR_ANY); setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &mreq, sizeof (mreq)); } /* if (ai_ptr->ai_family == AF_INET) */ else if (ai_ptr->ai_family == AF_INET6) { struct sockaddr_in6 *addr; struct ipv6_mreq mreq; int loop; addr = (struct sockaddr_in6 *) ai_ptr->ai_addr; if (!IN6_IS_ADDR_MULTICAST (&addr->sin6_addr)) { sockets_num++; continue; } loop = 1; setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (void *) &loop, sizeof (loop)); memset (&mreq, 0, sizeof (mreq)); memcpy (&mreq.ipv6mr_multiaddr, &addr->sin6_addr, sizeof (addr->sin6_addr)); mreq.ipv6mr_interface = 0; /* any */ setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (void *) &mreq, sizeof (mreq)); } /* if (ai_ptr->ai_family == AF_INET6) */ sockets_num++; } /* }}} for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */ freeaddrinfo (ai_list); if (sockets_num == 0) { sfree (sockets); return (-1); } *ret_sockets = sockets; *ret_sockets_num = sockets_num; return (0); } /* }}} int create_sockets */
static void handle_ip_packet(struct ip* iptr, int hw_dir) { int direction = 0; /* incoming */ history_type* ht; union { history_type **ht_pp; void **void_pp; } u_ht = { &ht }; addr_pair ap; unsigned int len = 0; struct in6_addr scribdst; /* Scratch pad. */ struct in6_addr scribsrc; /* Scratch pad. */ /* Reinterpret packet type. */ struct ip6_hdr* ip6tr = (struct ip6_hdr *) iptr; memset(&ap, '\0', sizeof(ap)); tick(0); if( (IP_V(iptr) ==4 && options.netfilter == 0) || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { /* * Net filter is off, so assign direction based on MAC address */ if(hw_dir == 1) { /* Packet leaving this interface. */ assign_addr_pair(&ap, iptr, 0); direction = 1; } else if(hw_dir == 0) { /* Packet incoming */ assign_addr_pair(&ap, iptr, 1); direction = 0; } /* Packet direction is not given away by h/ware layer. Try IP * layer */ else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_src)) { /* outgoing */ assign_addr_pair(&ap, iptr, 0); direction = 1; } else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_dst)) { /* incoming */ assign_addr_pair(&ap, iptr, 1); direction = 0; } else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_src)) { /* outgoing */ assign_addr_pair(&ap, iptr, 0); direction = 1; } else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) { /* incoming */ assign_addr_pair(&ap, iptr, 1); direction = 0; } else if (IP_V(iptr) == 4 && IN_MULTICAST(iptr->ip_dst.s_addr)) { assign_addr_pair(&ap, iptr, 1); direction = 0; } else if (IP_V(iptr) == 6 && IN6_IS_ADDR_MULTICAST(&ip6tr->ip6_dst)) { assign_addr_pair(&ap, iptr, 1); direction = 0; } /* * Cannot determine direction from hardware or IP levels. Therefore * assume that it was a packet between two other machines, assign * source and dest arbitrarily (by numerical value) and account as * incoming. */ else if (options.promiscuous_but_choosy) { return; /* junk it */ } else if((IP_V(iptr) == 4) && (iptr->ip_src.s_addr < iptr->ip_dst.s_addr)) { assign_addr_pair(&ap, iptr, 1); direction = 0; } else if(IP_V(iptr) == 4) { assign_addr_pair(&ap, iptr, 0); direction = 0; } /* Drop other uncertain packages. */ else return; } if(IP_V(iptr) == 4 && options.netfilter != 0) { /* * Net filter on, assign direction according to netmask */ if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) { /* out of network */ assign_addr_pair(&ap, iptr, 0); direction = 1; } else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) { /* into network */ assign_addr_pair(&ap, iptr, 1); direction = 0; } else { /* drop packet */ return ; } } if(IP_V(iptr) == 6 && options.netfilter6 != 0) { /* * Net filter IPv6 active. */ int j; //else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) { /* First reduce the participating addresses using the netfilter prefix. * We need scratch pads to do this. */ for (j=0; j < 16; ++j) { scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j] & options.netfilter6mask.s6_addr[j]; scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j] & options.netfilter6mask.s6_addr[j]; } /* Now look for any hits. */ //if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) { if (IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net) && ! IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) { /* out of network */ assign_addr_pair(&ap, iptr, 0); direction = 1; } //else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) { else if (! IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net) && IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) { /* into network */ assign_addr_pair(&ap, iptr, 1); direction = 0; } else { /* drop packet */ return ; } } #if 1 /* Test if link-local IPv6 packets should be dropped. */ if( IP_V(iptr) == 6 && !options.link_local && (IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_dst) || IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_src)) ) return; #endif /* Do address resolving. */ switch (IP_V(iptr)) { case 4: ap.protocol = iptr->ip_p; /* Add the addresses to be resolved */ /* The IPv4 address is embedded in a in6_addr structure, * so it need be copied, and delivered to resolve(). */ memset(&scribdst, '\0', sizeof(scribdst)); memcpy(&scribdst, &iptr->ip_dst, sizeof(struct in_addr)); resolve(ap.af, &scribdst, NULL, 0); memset(&scribsrc, '\0', sizeof(scribsrc)); memcpy(&scribsrc, &iptr->ip_src, sizeof(struct in_addr)); resolve(ap.af, &scribsrc, NULL, 0); break; case 6: ap.protocol = ip6tr->ip6_nxt; /* Add the addresses to be resolved */ resolve(ap.af, &ip6tr->ip6_dst, NULL, 0); resolve(ap.af, &ip6tr->ip6_src, NULL, 0); default: break; } if(hash_find(history, &ap, u_ht.void_pp) == HASH_STATUS_KEY_NOT_FOUND) { ht = history_create(); hash_insert(history, &ap, ht); } /* Do accounting. */ switch (IP_V(iptr)) { case 4: len = ntohs(iptr->ip_len); break; case 6: len = ntohs(ip6tr->ip6_plen) + 40; default: break; } /* Update record */ ht->last_write = history_pos; if( ((IP_V(iptr) == 4) && (iptr->ip_src.s_addr == ap.src.s_addr)) || ((IP_V(iptr) == 6) && !memcmp(&ip6tr->ip6_src, &ap.src6, sizeof(ap.src6))) ) { ht->sent[history_pos] += len; ht->total_sent += len; } else { ht->recv[history_pos] += len; ht->total_recv += len; } if(direction == 0) { /* incoming */ history_totals.recv[history_pos] += len; history_totals.total_recv += len; } else { history_totals.sent[history_pos] += len; history_totals.total_sent += len; } }
static DECL_CMD_FUNC(setvxlan_group, addr, d) { struct ifvxlancmd cmd; struct addrinfo *ai; struct sockaddr *sa; int error; bzero(&cmd, sizeof(cmd)); if ((error = getaddrinfo(addr, NULL, NULL, &ai)) != 0) errx(1, "error in parsing group address string: %s", gai_strerror(error)); sa = ai->ai_addr; switch (ai->ai_family) { #ifdef INET case AF_INET: { struct in_addr addr = ((struct sockaddr_in *)sa)->sin_addr; if (!IN_MULTICAST(ntohl(addr.s_addr))) errx(1, "group address must be multicast"); cmd.vxlcmd_sa.in4.sin_family = AF_INET; cmd.vxlcmd_sa.in4.sin_addr = addr; break; } #endif #ifdef INET6 case AF_INET6: { struct in6_addr *addr = &((struct sockaddr_in6 *)sa)->sin6_addr; if (!IN6_IS_ADDR_MULTICAST(addr)) errx(1, "group address must be multicast"); cmd.vxlcmd_sa.in6.sin6_family = AF_INET6; cmd.vxlcmd_sa.in6.sin6_addr = *addr; break; } #endif default: errx(1, "group address %s not supported", addr); } freeaddrinfo(ai); if (!vxlan_exists(s)) { if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) { params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4; params.vxlp_remote_in4 = cmd.vxlcmd_sa.in4.sin_addr; } else { params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR6; params.vxlp_remote_in6 = cmd.vxlcmd_sa.in6.sin6_addr; } return; } if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0) err(1, "VXLAN_CMD_SET_REMOTE_ADDR"); }
static gboolean socket_options_inet_setup_socket(SocketOptions *s, gint fd, GSockAddr *addr, AFSocketDirection dir) { SocketOptionsInet *self = (SocketOptionsInet *) s; gint off = 0; if (!socket_options_setup_socket_method(s, fd, addr, dir)) return FALSE; if (self->tcp_keepalive_time > 0) { #ifdef TCP_KEEPIDLE setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &self->tcp_keepalive_time, sizeof(self->tcp_keepalive_time)); #else msg_error("tcp-keepalive-time() is set but no TCP_KEEPIDLE setsockopt on this platform"); return FALSE; #endif } if (self->tcp_keepalive_probes > 0) { #ifdef TCP_KEEPCNT setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &self->tcp_keepalive_probes, sizeof(self->tcp_keepalive_probes)); #else msg_error("tcp-keepalive-probes() is set but no TCP_KEEPCNT setsockopt on this platform"); return FALSE; #endif } if (self->tcp_keepalive_intvl > 0) { #ifdef TCP_KEEPINTVL setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &self->tcp_keepalive_intvl, sizeof(self->tcp_keepalive_intvl)); #else msg_error("tcp-keepalive-intvl() is set but no TCP_KEEPINTVL setsockopt on this platform"); return FALSE; #endif } switch (addr->sa.sa_family) { case AF_INET: { struct ip_mreq mreq; if (IN_MULTICAST(ntohl(g_sockaddr_inet_get_address(addr).s_addr))) { if (dir & AFSOCKET_DIR_RECV) { memset(&mreq, 0, sizeof(mreq)); mreq.imr_multiaddr = g_sockaddr_inet_get_address(addr); mreq.imr_interface.s_addr = INADDR_ANY; setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &off, sizeof(off)); } if (dir & AFSOCKET_DIR_SEND) { if (self->ip_ttl) setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &self->ip_ttl, sizeof(self->ip_ttl)); } } else { if (self->ip_ttl && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IP, IP_TTL, &self->ip_ttl, sizeof(self->ip_ttl)); } if (self->ip_tos && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IP, IP_TOS, &self->ip_tos, sizeof(self->ip_tos)); break; } #if SYSLOG_NG_ENABLE_IPV6 case AF_INET6: { struct ipv6_mreq mreq6; if (IN6_IS_ADDR_MULTICAST(&g_sockaddr_inet6_get_sa(addr)->sin6_addr)) { if (dir & AFSOCKET_DIR_RECV) { memset(&mreq6, 0, sizeof(mreq6)); mreq6.ipv6mr_multiaddr = *g_sockaddr_inet6_get_address(addr); mreq6.ipv6mr_interface = 0; setsockopt(fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)); setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off)); } if (dir & AFSOCKET_DIR_SEND) { if (self->ip_ttl) setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &self->ip_ttl, sizeof(self->ip_ttl)); } } else { if (self->ip_ttl && (dir & AFSOCKET_DIR_SEND)) setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &self->ip_ttl, sizeof(self->ip_ttl)); } break; } #endif } return TRUE; }
BOOL Tcp::Open(PCSTR bindIp, INT bindPort) { int error = 0; int i_val = 0; UINT inIp; Close(); m_Socket= socket(AF_INET, SOCK_STREAM, IPPROTO_IP); if ( m_Socket == INVALID_SOCKET ) { ReportError(); return FALSE; } //i_val = 1; // 阻塞方式 //error = ioctlsocket(m_Socket, FIONBIO, (ULONG*)&i_val); //if (error == SOCKET_ERROR) //{ // ReportError(); // return FALSE; //} //设置使用keep alive i_val = 1; error = setsockopt(m_Socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&i_val, sizeof(i_val)); if ( error == SOCKET_ERROR ) { ReportError(); return FALSE; } tcp_keepalive inKeepAlive = {0}; tcp_keepalive outKeepAlive = {0}; u_long ulBytesReturn = 0; //keep alive为10秒3次 inKeepAlive.onoff = 1; inKeepAlive.keepaliveinterval = 10000; inKeepAlive.keepalivetime = 3; error = WSAIoctl(m_Socket, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, sizeof(inKeepAlive), (LPVOID)&outKeepAlive, sizeof(outKeepAlive), &ulBytesReturn, NULL, NULL); if ( error == SOCKET_ERROR ) { ReportError(); return FALSE; } // 可重用 i_val = 1; error = setsockopt(m_Socket, SOL_SOCKET, SO_REUSEADDR, (char*)&i_val, sizeof(i_val)); if (error == SOCKET_ERROR) { ReportError(); return FALSE; } // 绑定套接字 inIp = inet_addr(bindIp); m_BindAddr.sin_family = AF_INET; m_BindAddr.sin_port = htons(bindPort); m_BindAddr.sin_addr.s_addr = inIp; if (inIp == htonl(INADDR_ANY) || inIp == INADDR_BROADCAST || IN_MULTICAST(ntohl(inIp)) ) m_BindAddr.sin_addr.s_addr = htonl(INADDR_ANY); error = bind(m_Socket, (SOCKADDR*)&m_BindAddr, sizeof(m_BindAddr)); if (error == SOCKET_ERROR) { ReportError(); return FALSE; } m_isOpen = TRUE; return TRUE; }
static int ip_fw_chk(struct ip **pip, int hlen, struct ifnet *oif, u_int16_t *cookie, struct mbuf **m, struct ip_fw_chain **flow_id) { struct ip_fw_chain *chain; struct ip_fw *rule = NULL; struct ip *ip = NULL ; struct ifnet *const rif = (*m)->m_pkthdr.rcvif; u_short offset ; u_short src_port, dst_port; #ifdef IPFW_DIVERT_RESTART u_int16_t skipto = *cookie; #else u_int16_t ignport = ntohs(*cookie); #endif if (pip) { /* normal ip packet */ ip = *pip; offset = (ip->ip_off & IP_OFFMASK); } else { /* bridged or non-ip packet */ struct ether_header *eh = mtod(*m, struct ether_header *); switch (ntohs(eh->ether_type)) { case ETHERTYPE_IP : if ((*m)->m_len<sizeof(struct ether_header) + sizeof(struct ip)) goto non_ip ; ip = (struct ip *)(eh + 1 ); if (ip->ip_v != IPVERSION) goto non_ip ; hlen = ip->ip_hl << 2; if (hlen < sizeof(struct ip)) /* minimum header length */ goto non_ip ; if ((*m)->m_len < 14 + hlen + 14) { printf("-- m_len %d, need more...\n", (*m)->m_len); goto non_ip ; } offset = (ip->ip_off & IP_OFFMASK); break ; default : non_ip: ip = NULL ; break ; } } if (*flow_id) { if (fw_one_pass) return 0 ; /* accept if passed first test */ /* * pkt has already been tagged. Look for the next rule * to restart processing */ if ( (chain = (*flow_id)->rule->next_rule_ptr) == NULL ) chain = (*flow_id)->rule->next_rule_ptr = lookup_next_rule(*flow_id) ; if (!chain) goto dropit; } else { chain=LIST_FIRST(&ip_fw_chain); #ifdef IPFW_DIVERT_RESTART if ( skipto ) { /* * If we've been asked to start at a given rule immediatly, * do so. */ if (skipto >= 65535) goto dropit; while (chain && (chain->rule->fw_number <= skipto)) { chain = LIST_NEXT(chain, chain); } if (! chain) goto dropit; } #endif /* IPFW_DIVERT_RESTART */ } *cookie = 0; for (; chain; chain = LIST_NEXT(chain, chain)) { register struct ip_fw *f; again: f = chain->rule; if (oif) { /* Check direction outbound */ if (!(f->fw_flg & IP_FW_F_OUT)) continue; } else { /* Check direction inbound */ if (!(f->fw_flg & IP_FW_F_IN)) continue; } if (ip == NULL ) { /* * do relevant checks for non-ip packets: * after this, only goto got_match or continue */ struct ether_header *eh = mtod(*m, struct ether_header *); int i, h, l ; #if 0 printf("-- ip_fw: rule %d(%d) for %6D <- %6D type 0x%04x\n", f->fw_number, IP_FW_GETNSRCP(f), eh->ether_dhost, ".", eh->ether_shost, ".", ntohs(eh->ether_type) ); #endif /* * make default rule always match or we have a panic */ if (f->fw_number == 65535) goto got_match ; /* * temporary hack: * udp from 0.0.0.0 means this rule applies. * 1 src port is match ether type * 2 src ports (interval) is match ether type * 3 src ports is match ether address */ if (f->fw_src.s_addr != 0 || f->fw_prot != IPPROTO_UDP) continue ; switch (IP_FW_GETNSRCP(f)) { case 1: /* match one type */ if ( /* ( (f->fw_flg & IP_FW_F_INVSRC) != 0) ^ */ ( f->fw_pts[0] == ntohs(eh->ether_type) ) ) { printf("match!\n"); goto got_match ; } default: break ; } continue; } /* Fragments */ if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK)) continue; /* If src-addr doesn't match, not this rule. */ if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((ip->ip_src.s_addr & f->fw_smsk.s_addr) != f->fw_src.s_addr)) continue; /* If dest-addr doesn't match, not this rule. */ if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((ip->ip_dst.s_addr & f->fw_dmsk.s_addr) != f->fw_dst.s_addr)) continue; /* Interface check */ if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) { struct ifnet *const iface = oif ? oif : rif; /* Backwards compatibility hack for "via" */ if (!iface || !iface_match(iface, &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME)) continue; } else { /* Check receive interface */ if ((f->fw_flg & IP_FW_F_IIFACE) && (!rif || !iface_match(rif, &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME))) continue; /* Check outgoing interface */ if ((f->fw_flg & IP_FW_F_OIFACE) && (!oif || !iface_match(oif, &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME))) continue; } /* Check IP options */ if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f)) continue; /* Check protocol; if wildcard, match */ if (f->fw_prot == IPPROTO_IP) goto got_match; /* If different, don't match */ if (ip->ip_p != f->fw_prot) continue; #define PULLUP_TO(len) do { \ if ((*m)->m_len < (len) ) { \ if ( (*m = m_pullup(*m, (len))) == 0) \ goto bogusfrag; \ *pip = ip = mtod(*m, struct ip *); \ offset = (ip->ip_off & IP_OFFMASK); \ } \ } while (0) /* Protocol specific checks */ switch (ip->ip_p) { case IPPROTO_TCP: { struct tcphdr *tcp; if (offset == 1) /* cf. RFC 1858 */ goto bogusfrag; if (offset != 0) { /* * TCP flags and ports aren't available in this * packet -- if this rule specified either one, * we consider the rule a non-match. */ if (f->fw_nports != 0 || f->fw_tcpf != f->fw_tcpnf) continue; break; } PULLUP_TO(hlen + 14); tcp = (struct tcphdr *) ((u_long *)ip + ip->ip_hl); if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f)) continue; src_port = ntohs(tcp->th_sport); dst_port = ntohs(tcp->th_dport); goto check_ports; } case IPPROTO_UDP: { struct udphdr *udp; if (offset != 0) { /* * Port specification is unavailable -- if this * rule specifies a port, we consider the rule * a non-match. */ if (f->fw_nports != 0) continue; break; } PULLUP_TO(hlen + 4); udp = (struct udphdr *) ((u_long *)ip + ip->ip_hl); src_port = ntohs(udp->uh_sport); dst_port = ntohs(udp->uh_dport); check_ports: if (!port_match(&f->fw_pts[0], IP_FW_GETNSRCP(f), src_port, f->fw_flg & IP_FW_F_SRNG)) continue; if (!port_match(&f->fw_pts[IP_FW_GETNSRCP(f)], IP_FW_GETNDSTP(f), dst_port, f->fw_flg & IP_FW_F_DRNG)) continue; break; } case IPPROTO_ICMP: { struct icmp *icmp; if (offset != 0) /* Type isn't valid */ break; PULLUP_TO(hlen + 2); icmp = (struct icmp *) ((u_long *)ip + ip->ip_hl); if (!icmptype_match(icmp, f)) continue; break; } #undef PULLUP_TO bogusfrag: if (fw_verbose) ipfw_report(NULL, ip, rif, oif); goto dropit; } got_match: *flow_id = chain ; /* XXX set flow id */ #ifndef IPFW_DIVERT_RESTART /* Ignore divert/tee rule if socket port is "ignport" */ switch (f->fw_flg & IP_FW_F_COMMAND) { case IP_FW_F_DIVERT: case IP_FW_F_TEE: if (f->fw_divert_port == ignport) continue; /* ignore this rule */ break; } #endif /* IPFW_DIVERT_RESTART */ /* Update statistics */ f->fw_pcnt += 1; /* * note -- bridged-ip packets still have some fields * in network order, including ip_len */ if (ip) { if (pip) f->fw_bcnt += ip->ip_len; else f->fw_bcnt += ntohs(ip->ip_len); } f->timestamp = time.tv_sec; /* Log to console if desired */ if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose) ipfw_report(f, ip, rif, oif); /* Take appropriate action */ switch (f->fw_flg & IP_FW_F_COMMAND) { case IP_FW_F_ACCEPT: return(0); case IP_FW_F_COUNT: continue; #ifdef IPDIVERT case IP_FW_F_DIVERT: #ifdef IPFW_DIVERT_RESTART *cookie = f->fw_number; #else *cookie = htons(f->fw_divert_port); #endif /* IPFW_DIVERT_RESTART */ return(f->fw_divert_port); #endif case IP_FW_F_TEE: /* * XXX someday tee packet here, but beware that you * can't use m_copym() or m_copypacket() because * the divert input routine modifies the mbuf * (and these routines only increment reference * counts in the case of mbuf clusters), so need * to write custom routine. */ continue; case IP_FW_F_SKIPTO: /* XXX check */ if ( f->next_rule_ptr ) chain = f->next_rule_ptr ; else chain = lookup_next_rule(chain) ; if (!chain) goto dropit; goto again ; #ifdef DUMMYNET case IP_FW_F_PIPE: return(f->fw_pipe_nr | 0x10000 ); #endif } /* Deny/reject this packet using this rule */ rule = f; break; } #ifdef DIAGNOSTIC /* Rule 65535 should always be there and should always match */ if (!chain) panic("ip_fw: chain"); #endif /* * At this point, we're going to drop the packet. * Send a reject notice if all of the following are true: * * - The packet matched a reject rule * - The packet is not an ICMP packet, or is an ICMP query packet * - The packet is not a multicast or broadcast packet */ if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT && ip && (ip->ip_p != IPPROTO_ICMP || is_icmp_query(ip)) && !((*m)->m_flags & (M_BCAST|M_MCAST)) && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { switch (rule->fw_reject_code) { case IP_FW_REJECT_RST: { struct tcphdr *const tcp = (struct tcphdr *) ((u_long *)ip + ip->ip_hl); struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip; if (offset != 0 || (tcp->th_flags & TH_RST)) break; ti.ti_i = *((struct ipovly *) ip); ti.ti_t = *tcp; bcopy(&ti, ip, sizeof(ti)); NTOHL(tip->ti_seq); NTOHL(tip->ti_ack); tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2); if (tcp->th_flags & TH_ACK) { tcp_respond(NULL, tip, *m, (tcp_seq)0, ntohl(tcp->th_ack), TH_RST); } else { if (tcp->th_flags & TH_SYN) tip->ti_len++; tcp_respond(NULL, tip, *m, tip->ti_seq + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK); } *m = NULL; break; } default: /* Send an ICMP unreachable using code */ icmp_error(*m, ICMP_UNREACH, rule->fw_reject_code, 0L, 0); *m = NULL; break; } } dropit: /* * Finally, drop the packet. */ if (*m) { m_freem(*m); *m = NULL; } return(0); }
intptr_t udp_open(char *src_addr, char *addr, unsigned short port, char *mode) { struct udp *udp; udp = (struct udp *)malloc(sizeof(struct udp)); if(NULL == udp) { RPT(RPT_ERR, "malloc failed"); return (intptr_t)NULL; } strcpy(udp->addr, addr); udp->src_addr[0] = '\0'; if(src_addr) { strcpy(udp->src_addr, src_addr); } #ifdef SYS_WINDOWS WSADATA wsaData; if(WSAStartup(MAKEWORD(1,1), &wsaData) == SOCKET_ERROR) { RPT(RPT_ERR, "WSAStartup error"); return (intptr_t)NULL; } #endif /* build socket */ if((udp->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { report("socket failed"); return (intptr_t)NULL; } /* nonblock mode */ #ifdef SYS_WINDOWS { unsigned long opt = 1; ioctlsocket(udp->sock, FIONBIO, &opt); } #else { fcntl(udp->sock, F_SETFL, O_NONBLOCK); } #endif /* reuse address */ { int reuseaddr = 1; /* nonzero means enable */ setsockopt(udp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseaddr, sizeof(int)); } /* name the socket */ { struct sockaddr_in local; memset(&local, 0, sizeof(local)); /* for some special compile environment */ local.sin_family = AF_INET; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = ('r' == mode[0]) ? htons(port) : 0; if(bind(udp->sock, (struct sockaddr *)&local, sizeof(struct sockaddr)) < 0) { report("bind failed"); fprintf(stderr, "addr: %s, port: %d\n", inet_ntoa(local.sin_addr), ntohs(local.sin_port)); return (intptr_t)NULL; } } /* set the remote */ if('w' == mode[0]) { udp->remote.sin_family = AF_INET; udp->remote.sin_addr.s_addr = inet_addr(addr); udp->remote.sin_port = htons(port); } /* manage multicast */ if(IN_MULTICAST(ntohl(inet_addr(udp->addr)))) { if('\0' == udp->src_addr[0]) { struct ip_mreq imreq; RPT(RPT_INF, "IP_ADD_MEMBERSHIP: %s", udp->addr); imreq.imr_interface.s_addr = htonl(INADDR_ANY); imreq.imr_multiaddr.s_addr = inet_addr(udp->addr); if(setsockopt(udp->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imreq, sizeof(imreq)) != 0) { report("IP_ADD_MEMBERSHIP failed"); } } else { struct ip_mreq_source mreqsrc; RPT(RPT_INF, "IP_ADD_SOURCE_MEMBERSHIP: %s@%s", udp->src_addr, udp->addr); mreqsrc.imr_interface.s_addr = htonl(INADDR_ANY); mreqsrc.imr_multiaddr.s_addr = inet_addr(udp->addr); mreqsrc.imr_sourceaddr.s_addr = inet_addr(udp->src_addr); if(setsockopt(udp->sock, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *)&mreqsrc, sizeof(mreqsrc)) != 0) { report("IP_ADD_SOURCE_MEMBERSHIP failed"); } } } udp->socklen = sizeof(struct sockaddr_in); return (intptr_t)udp; }
void handle_igmpv3_isex( __u32 group, __u32 src, int srcnum, __u32 *grec_src ) { struct mcft_entry *mymcp; // Mason Yu Test //printf("handle_igmpv3_isex\n"); if(!IN_MULTICAST(group)) return; /* check if it's protocol reserved group */ if((group&0xFFFFFF00)==0xE0000000){ //printf("[%s]:It's protocol | reserved group!\n",__FUNCTION__); return; } if(!chk_mcft(group)) { //return; mymcp = add_mcft(group, src); if(!mymcp) return; mymcp->igmp_ver = IGMP_VER_3; igmp_add_group( group ); } mymcp = get_mcft(group); if(mymcp) { switch( mymcp->filter_mode ) { case MCAST_INCLUDE: { int i; struct src_entry *s, *old_set,*s_next; // Mason Yu Test //printf("handle_igmpv3_isex: MCAST_INCLUDE\n"); #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif //IN(A), IS_EX(B) => EX(A*B, B-A) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { //(B-A)=0 if (check_src_set(grec_src[i],old_set)==0) { s = add_to_srclist( mymcp, grec_src[i] ); if(s) { s->timer.lefttime = 0; s->timer.retry_left = 0; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 0 ); } } } s = old_set; while(s) { s_next=s->next; //Delete (A-B) if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { igmp_del_mr( mymcp->grp_addr, s->srcaddr ); del_from_srclist( mymcp, s->srcaddr ); } s = s_next; } //Group Timer=GMI mymcp->timer.lefttime = MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left = MEMBER_QUERY_COUNT; //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } break; case MCAST_EXCLUDE: { int i; struct src_entry *s, *old_set,*s_next; // Mason Yu Test //printf("handle_igmpv3_isex: MCAST_EXCLUDE\n"); #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif //EX(X,Y), IS_EX(A) => EX(A-Y, Y*A) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { // (A-X-Y)=GMI if( check_src_set( grec_src[i],old_set )==0 ) { s=add_to_srclist( mymcp, grec_src[i] ); if(s) { s->timer.lefttime = MEMBER_QUERY_INTERVAL; s->timer.retry_left = MEMBER_QUERY_COUNT; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 1 ); } } } s = old_set; while(s) { s_next =s->next; //Delete (X-A), Delete(Y-A) if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { igmp_del_mr( mymcp->grp_addr, s->srcaddr ); del_from_srclist( mymcp, s->srcaddr ); } s = s_next; } //Group Timer=GMI mymcp->timer.lefttime = MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left = MEMBER_QUERY_COUNT; //printf("grp_addr:%s.mymcp->timer.lefttime=%d,mymcp->timer.retry_left=%d,[%s]:[%d].\n",inet_ntoa(group),mymcp->timer.lefttime,mymcp->timer.retry_left,__FUNCTION__,__LINE__); //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } break; default: break; } } }
bool UdpComm::joinMulticast(const char* addrStr) { sockaddr_in group; if(!resolve(addrStr, 0, &group)) return false; //join multicast group for every interface if(IN_MULTICAST(ntohl(group.sin_addr.s_addr))) { #ifndef WINDOWS ip_mreq mreq; ifconf ifc; ifreq* item; char buf[1024]; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(sock, SIOCGIFCONF, &ifc) < 0) { std::cerr << "cannot get interface list" << std::endl; return false; } else { bool could_join(false); for(unsigned int i = 0; i < ifc.ifc_len / sizeof(ifreq); i++) { item = &ifc.ifc_req[i]; mreq.imr_multiaddr = group.sin_addr; mreq.imr_interface = ((sockaddr_in*)&item->ifr_addr)->sin_addr; if(0 == setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&mreq, sizeof(mreq))) could_join = true; } if(!could_join) { std::cerr << "join multicast group failed for interface" << std::endl; return false; } } #else char host[128]; hostent* pHost; if(gethostname(host, sizeof(host)) < 0 || !(pHost = (hostent*)gethostbyname(host))) { std::cerr << "cannot get interface list" << std::endl; return false; } ip_mreq mreq; bool couldJoin(false); for(int i = 0; pHost->h_addr_list[i]; i++) { mreq.imr_multiaddr = group.sin_addr; mreq.imr_interface = *((in_addr*)pHost->h_addr_list[i]); if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq)) == 0) couldJoin = true; } if(!couldJoin) { std::cerr << "join multicast group failed for interface" << std::endl; return false; } #endif return true; } else std::cerr << "not a multicast address" << std::endl; return false; }
void handle_igmpv3_isin( __u32 group, __u32 src, int srcnum, __u32 *grec_src ) { struct mcft_entry *mymcp; if(!IN_MULTICAST(group)) return; /* check if it's protocol reserved group */ if((group&0xFFFFFF00)==0xE0000000) return; if(!chk_mcft(group)) { mymcp = add_mcft(group, src); if(!mymcp) return; mymcp->igmp_ver = IGMP_VER_3; igmp_add_group( group ); } mymcp = get_mcft(group); if(mymcp) { switch( mymcp->filter_mode ) { case MCAST_INCLUDE: { int i; struct src_entry *s, *old_set; //printf("handle_igmpv3_isin: MCAST_INCLUDE\n"); #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif //IN(A), IN(B) => IN(A+B) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { if( check_src_set(grec_src[i], old_set )==0 ) igmp_add_mr( mymcp->grp_addr, grec_src[i], 1 ); // (B)= GMI s = add_to_srclist( mymcp, grec_src[i] ); if (s) { s->timer.lefttime = MEMBER_QUERY_INTERVAL; s->timer.retry_left = MEMBER_QUERY_COUNT; } } //set the new state mymcp->filter_mode = MCAST_INCLUDE; igmp_set_srcfilter( mymcp ); } break; case MCAST_EXCLUDE: { int i; struct src_entry *s, *old_set; //printf("handle_igmpv3_isin: MCAST_EXCLUDE\n"); //EX(X,Y), IS_IN(A) => EX(X+A, Y-A) #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { s = add_to_srclist( mymcp, grec_src[i] ); if(s) { // (A)= GMI s->timer.lefttime = MEMBER_QUERY_INTERVAL; s->timer.retry_left = MEMBER_QUERY_COUNT; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 1 ); } } //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } break; default: break; } } }
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; int isatap = 0; memset(p, 0, sizeof(*p)); memset(&medium, 0, sizeof(medium)); p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { set_tunnel_proto(p, IPPROTO_IPIP); } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { set_tunnel_proto(p, IPPROTO_GRE); } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { set_tunnel_proto(p, IPPROTO_IPV6); } else if (strcmp(*argv, "isatap") == 0) { set_tunnel_proto(p, IPPROTO_IPV6); isatap++; } else if (strcmp(*argv, "vti") == 0) { set_tunnel_proto(p, IPPROTO_IPIP); p->i_flags |= VTI_ISVTI; } else { fprintf(stderr, "Unknown tunnel mode \"%s\"\n", *argv); exit(-1); } } else if (strcmp(*argv, "key") == 0) { NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; p->i_key = p->o_key = tnl_parse_key("key", *argv); } else if (strcmp(*argv, "ikey") == 0) { NEXT_ARG(); p->i_flags |= GRE_KEY; p->i_key = tnl_parse_key("ikey", *argv); } else if (strcmp(*argv, "okey") == 0) { NEXT_ARG(); p->o_flags |= GRE_KEY; p->o_key = tnl_parse_key("okey", *argv); } else if (strcmp(*argv, "seq") == 0) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "iseq") == 0) { p->i_flags |= GRE_SEQ; } else if (strcmp(*argv, "oseq") == 0) { p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "csum") == 0) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "icsum") == 0) { p->i_flags |= GRE_CSUM; } else if (strcmp(*argv, "ocsum") == 0) { p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "nopmtudisc") == 0) { p->iph.frag_off = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.daddr = get_addr32(*argv); else p->iph.daddr = htonl(INADDR_ANY); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.saddr = get_addr32(*argv); else p->iph.saddr = htonl(INADDR_ANY); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ - 1); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0 || strcmp(*argv, "hlim") == 0) { __u8 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_u8(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); p->iph.ttl = uval; } } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { char *dsfield; __u32 uval; NEXT_ARG(); dsfield = *argv; strsep(&dsfield, "/"); if (strcmp(*argv, "inherit") != 0) { dsfield = *argv; p->iph.tos = 0; } else p->iph.tos = 1; if (dsfield) { if (rtnl_dsfield_a2n(&uval, dsfield)) invarg("bad TOS value", *argv); p->iph.tos |= uval; } } else { if (strcmp(*argv, "name") == 0) NEXT_ARG(); else if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ - 1); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; else if (memcmp(p->name, "isatap", 6) == 0) { p->iph.protocol = IPPROTO_IPV6; isatap++; } else if (memcmp(p->name, "vti", 3) == 0) { p->iph.protocol = IPPROTO_IPIP; p->i_flags |= VTI_ISVTI; } } if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { if (!(p->i_flags & VTI_ISVTI) && (p->iph.protocol != IPPROTO_GRE)) { fprintf(stderr, "Keys are not allowed with ipip and sit tunnels\n"); return -1; } } if (medium[0]) { p->link = ll_name_to_index(medium); if (p->link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", medium); return -1; } } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { fprintf(stderr, "A broadcast tunnel requires a source address\n"); return -1; } if (isatap) p->i_flags |= SIT_ISATAP; return 0; }
void handle_igmpv3_toex( __u32 group, __u32 src, int srcnum, __u32 *grec_src ) { struct mcft_entry *mymcp; if(!IN_MULTICAST(group)) return; /* check if it's protocol reserved group */ if((group&0xFFFFFF00)==0xE0000000) return; if(!chk_mcft(group)) { mymcp = add_mcft(group, src); if(!mymcp) return; mymcp->igmp_ver = IGMP_VER_3; igmp_add_group( group ); } mymcp = get_mcft(group); if(mymcp) { switch( mymcp->filter_mode ) { case MCAST_INCLUDE: { int i; struct src_entry *s, *old_set,*s_next; //printf("handle_igmpv3_toex: MCAST_INCLUDE\n"); #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif //IN(A), TO_EX(B) => EX(A*B, B-A) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { // (B-A)=0 if( check_src_set(grec_src[i], old_set )==0 ) { s = add_to_srclist( mymcp, grec_src[i] ); if(s){ s->timer.lefttime = 0; s->timer.retry_left = 0; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 0 ); } } } i=0; s = old_set; while(s) { s_next=s->next; //Delete (A-B) if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { igmp_del_mr( mymcp->grp_addr, s->srcaddr ); del_from_srclist( mymcp, s->srcaddr ); } else { /*lower A*B timer to LMQT*/ gsrctmp[i]=s->srcaddr; s->timer.lefttime=LAST_MEMBER_QUERY_INTERVAL; s->timer.retry_left=LAST_MEMBER_QUERY_COUNT; i++; if(i==IGMPV3_MAX_SRCNUM) break; } s = s_next; } //send Q(G,A*B) if(i>0) igmpv3_query( mymcp, i, gsrctmp ); //Group Timer=GMI mymcp->timer.lefttime = MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left = MEMBER_QUERY_COUNT; //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } break; case MCAST_EXCLUDE: { int i; struct src_entry *s, *old_set,*s_next; //printf("handle_igmpv3_toex: MCAST_EXCLUDE\n"); #ifdef KEEP_GROUP_MEMBER add_user(mymcp, src); #endif //EX(X,Y), TO_EX(A) => EX(A-Y, Y*A) old_set = mymcp->srclist; for(i=0;i<srcnum;i++) { if( check_src_set( grec_src[i], old_set )==0 ) { // (A-X-Y)=Group Timer s = add_to_srclist( mymcp, grec_src[i] ); if(s){ s->timer.lefttime = mymcp->timer.lefttime; s->timer.retry_left = MEMBER_QUERY_COUNT; igmp_add_mr( mymcp->grp_addr, s->srcaddr, 1 ); } } } s = old_set; while(s) { s_next=s->next; //Delete (X-A), Delete(Y-A) if( check_src( s->srcaddr, grec_src, srcnum )==0 ) { igmp_del_mr( mymcp->grp_addr, s->srcaddr ); del_from_srclist( mymcp, s->srcaddr ); } s = s_next; } //send Q(G,A-Y) i=0; s = mymcp->srclist; while(s) { s_next=s->next; if( s->timer.lefttime > 0 )//A-Y { gsrctmp[i]=s->srcaddr; /*lower A-Y timer to LMQT*/ s->timer.lefttime=LAST_MEMBER_QUERY_INTERVAL; s->timer.retry_left=LAST_MEMBER_QUERY_COUNT; i++; if(i==IGMPV3_MAX_SRCNUM) break; } s=s_next; } if(i>0) igmpv3_query( mymcp, i, gsrctmp ); //Group Timer=GMI mymcp->timer.lefttime = MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left = MEMBER_QUERY_COUNT; //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } break; default: break; } } }
/* * parse_args() * Parse argv, and return parsed info in **relays, *relay_count, and * *is_server. On failure, exit. */ static void parse_args(int argc, char *argv[], struct relay **relays, int *relay_count, int *is_server) { int c; char *tcphostname, *tcpportstr, *udphostname, *udpportstr, *udpttlstr; struct in_addr tcpaddr, udpaddr; int tcpport, udpport, udpttl; int i; *is_server = -1; *relay_count = 1; debug = 0; tcphostname = NULL; tcpportstr = NULL; while ((c = getopt(argc, argv, "s:c:rvh")) != EOF) { switch (c) { case 's': if (*is_server != -1) { fprintf(stderr, "%s: Only one of -s and -c may be specified.\n", argv[0]); exit(2); } *is_server = 1; tcpportstr = optarg; break; case 'c': if (*is_server != -1) { fprintf(stderr, "%s: Only one of -s and -c may be specified.\n", argv[0]); exit(2); } *is_server = 0; tcphostname = optarg; break; case 'r': *relay_count = 2; break; case 'v': debug++; break; case 'h': case '?': default: usage(argv[0]); break; } } if (*is_server == -1) { fprintf(stderr, "%s: You must specify one of -s and -c.\n", argv[0]); exit(2); } if (argc <= optind) { usage(argv[0]); } udphostname = strtok(argv[optind], ":/ "); udpportstr = strtok(NULL, ":/ "); if (udpportstr == NULL) { usage(argv[0]); } udpttlstr = strtok(NULL, ":/ "); if (!*is_server) { tcphostname = strtok(tcphostname, ":/ "); tcpportstr = strtok(NULL, ":/ "); } else { tcphostname = NULL; } errno = 0; udpport = strtol(udpportstr, NULL, 0); if (errno || udpport <= 0 || udpport >= 65536) { fprintf(stderr, "%s: invalid port number\n", udpportstr); exit(2); } if (udpttlstr != NULL) { errno = 0; udpttl = strtol(udpttlstr, NULL, 0); if (errno || udpttl < 0 || udpttl >= 256) { fprintf(stderr, "%s: invalid TTL\n", udpttlstr); exit(2); } } else { udpttl = 1; } if (tcpportstr != NULL) { errno = 0; tcpport = strtol(tcpportstr, NULL, 0); if (errno || tcpport <= 0 || tcpport >= 65536) { fprintf(stderr, "%s: invalid port number\n", tcpportstr); exit(2); } } else { tcpport = udpport; } if (*relay_count == 2 && (tcpport % 2 != 0 || udpport % 2 != 0)) { fprintf(stderr, "Port numbers must be even when using RTP mode.\n"); exit(2); } udpaddr = host2ip(udphostname); if (udpaddr.s_addr == INADDR_ANY) { fprintf(stderr, "%s: UDP host unknown\n", udphostname); exit(2); } if (*is_server) { tcpaddr.s_addr = INADDR_ANY; } else { tcpaddr = host2ip(tcphostname); if (tcpaddr.s_addr == INADDR_ANY) { fprintf(stderr, "%s: TCP host unknown\n", tcphostname); exit(2); } } *relays = (struct relay *) calloc(*relay_count, sizeof(struct relay)); if (relays == NULL) { perror("Error allocating relay structure"); exit(1); } for (i = 0; i < *relay_count; i++) { (*relays)[i].udpaddr.sin_addr = udpaddr; (*relays)[i].udpaddr.sin_port = htons(udpport + i); (*relays)[i].udpaddr.sin_family = AF_INET; (*relays)[i].udp_ttl = udpttl; (*relays)[i].multicast_udp = IN_MULTICAST(htons(udpaddr.s_addr)); (*relays)[i].tcpaddr.sin_addr = tcpaddr; (*relays)[i].tcpaddr.sin_port = htons(tcpport + i); (*relays)[i].tcpaddr.sin_family = AF_INET; } } /* parse_args */
int in_pcbbind(struct inpcb *inp, struct mbuf *nam) { register struct socket *so = inp->inp_socket; unsigned short *lastport; struct sockaddr_in *sin; u_short lport = 0; int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); int error; if (in_ifaddr == 0) return (EADDRNOTAVAIL); if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 && ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 || (so->so_options & SO_ACCEPTCONN) == 0)) wild = 1; if (nam) { sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) return (EINVAL); #ifdef notdef /* * We should check the family, but old programs * incorrectly fail to initialize it. */ if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); #endif lport = sin->sin_port; if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { /* * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; * allow complete duplication of binding if * SO_REUSEPORT is set, or if SO_REUSEADDR is set * and a multicast address is bound on both * new and duplicated sockets. */ if (so->so_options & SO_REUSEADDR) reuseport = SO_REUSEADDR|SO_REUSEPORT; } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) return (EADDRNOTAVAIL); } if (lport) { struct inpcb *t; /* GROSS */ if (ntohs(lport) < IPPORT_RESERVED && (error = suser(p->p_ucred, &p->p_acflag))) return (EACCES); if (so->so_uid) { t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, sin->sin_addr, lport, INPLOOKUP_WILDCARD); if (t && (so->so_uid != t->inp_socket->so_uid)) return (EADDRINUSE); } t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, sin->sin_addr, lport, wild); if (t && (reuseport & t->inp_socket->so_options) == 0) return (EADDRINUSE); } inp->inp_laddr = sin->sin_addr; } if (lport == 0) { unsigned short first, last; int count; inp->inp_flags |= INP_ANONPORT; if (inp->inp_flags & INP_HIGHPORT) { first = ipport_hifirstauto; /* sysctl */ last = ipport_hilastauto; lastport = &inp->inp_pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { if ((error = suser(p->p_ucred, &p->p_acflag))) return (EACCES); first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ lastport = &inp->inp_pcbinfo->lastlow; } else { first = ipport_firstauto; /* sysctl */ last = ipport_lastauto; lastport = &inp->inp_pcbinfo->lastport; } /* * Simple check to ensure all ports are not used up causing * a deadlock here. * * We split the two cases (up and down) so that the direction * is not being tested on each round of the loop. */ if (first > last) { /* * counting down */ count = first - last; do { if (count-- <= 0) /* completely used? */ return (EADDRNOTAVAIL); --*lastport; if (*lastport > first || *lastport < last) *lastport = first; lport = htons(*lastport); } while (in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, inp->inp_laddr, lport, wild)); } else { /* * counting up */ count = last - first; do { if (count-- <= 0) /* completely used? */ return (EADDRNOTAVAIL); ++*lastport; if (*lastport < first || *lastport > last) *lastport = first; lport = htons(*lastport); } while (in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, inp->inp_laddr, lport, wild)); } } inp->inp_lport = lport; in_pcbrehash(inp); return (0); }
int sdputil_init(SDP_DESCR_T *pSdp, uint8_t payloadType, unsigned int clockRateHz, XC_CODEC_TYPE_T codecType, const char *pDstHost, uint16_t dstPort, uint16_t dstPortRtcp, const SRTP_CTXT_T *pSrtp, const DTLS_CFG_T *pDtlsCfg, const STUN_REQUESTOR_CFG_T *pStunCfg, const SDP_CODEC_PARAM_T *pCodecSpecific, const FRAME_RATE_T *pFps, const VID_ENCODER_FBREQUEST_T *pFbReq) { int rc = 0; struct in_addr connectip; if(!pSdp || payloadType > 0x7f || !pDstHost) { return -1; } memset(&connectip, 0, sizeof(connectip)); connectip.s_addr = inet_addr(pDstHost); if(connectip.s_addr != INADDR_NONE && IN_MULTICAST( htonl(connectip.s_addr) )) { pSdp->c.ttl = 64; } else if(connectip.s_addr != INADDR_NONE && IN_LOCALHOST( htonl(connectip.s_addr) )) { pSdp->c.ttl = 0; } else { //connectip.s_addr = net_getlocalip(); // // For remote unicast destinations, leave the remote ip into the 'c=' field // which may be contrary to RFC4566 // //connectip.s_addr = INADDR_ANY; pSdp->c.ttl = 0; } strncpy(pSdp->c.iphost, inet_ntoa(connectip), sizeof(pSdp->c.iphost)); // // Only write the RTCP port attribute in the SDP if using a non-default port // if(dstPortRtcp == RTCP_PORT_FROM_RTP(dstPort)) { dstPortRtcp = 0; } if(pFps && pFps->clockHz > 0 && pFps->frameDeltaHz > 0) { memcpy(&pSdp->vid.fps, pFps, sizeof(pSdp->vid.fps)); } switch(codecType) { case XC_CODEC_TYPE_H264: case XC_CODEC_TYPE_MPEG4V: case XC_CODEC_TYPE_H263: case XC_CODEC_TYPE_H263_PLUS: case XC_CODEC_TYPE_VP8: pSdp->vid.common.available = 1; pSdp->vid.common.codecType = codecType; pSdp->vid.common.payloadType = payloadType; pSdp->vid.common.port = dstPort; pSdp->vid.common.portRtcp = dstPortRtcp; pSdp->vid.common.clockHz = clockRateHz; pSdp->vid.common.transType = SDP_TRANS_TYPE_RTP_UDP; if(pDtlsCfg) { if(pDtlsCfg->dtls_srtp) { pSdp->vid.common.transType = SDP_TRANS_TYPE_SRTP_DTLS_UDP; } else { pSdp->vid.common.transType = SDP_TRANS_TYPE_DTLS_UDP; } memcpy(&pSdp->vid.common.fingerprint, &pDtlsCfg->fingerprint, sizeof(pSdp->vid.common.fingerprint)); } if(pSrtp) { pSdp->vid.common.transType = SDP_TRANS_TYPE_SRTP_SDES_UDP; if((rc = sdputil_initsrtp(&pSdp->vid.common.srtp, pSrtp)) < 0) { return rc; } } if(pStunCfg && pStunCfg->bindingRequest) { if(pStunCfg->reqUsername) { strncpy(pSdp->vid.common.ice.ufrag, pStunCfg->reqUsername, STUN_STRING_MAX - 1); } if(pStunCfg->reqPass) { strncpy(pSdp->vid.common.ice.pwd, pStunCfg->reqPass, STUN_STRING_MAX - 1); } } if(codecType == XC_CODEC_TYPE_H264) { strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H264, sizeof(pSdp->vid.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_MPEG4V) { strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_MPEG4V, sizeof(pSdp->vid.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_H263) { strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H263, sizeof(pSdp->vid.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_H263_PLUS) { strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_H263_PLUS, sizeof(pSdp->vid.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_VP8) { strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_VP8, sizeof(pSdp->vid.common.encodingName)); } break; case XC_CODEC_TYPE_AAC: case XC_CODEC_TYPE_AMRNB: case XC_CODEC_TYPE_SILK: case XC_CODEC_TYPE_OPUS: case XC_CODEC_TYPE_G711_MULAW: case XC_CODEC_TYPE_G711_ALAW: pSdp->aud.common.available = 1; pSdp->aud.common.codecType = codecType; pSdp->aud.common.payloadType = payloadType; pSdp->aud.common.port = dstPort; pSdp->aud.common.portRtcp = dstPortRtcp; pSdp->aud.common.clockHz = clockRateHz; pSdp->aud.common.transType = SDP_TRANS_TYPE_RTP_UDP; if(pDtlsCfg) { if(pDtlsCfg->dtls_srtp) { pSdp->aud.common.transType = SDP_TRANS_TYPE_SRTP_DTLS_UDP; } else { pSdp->aud.common.transType = SDP_TRANS_TYPE_DTLS_UDP; } memcpy(&pSdp->aud.common.fingerprint, &pDtlsCfg->fingerprint, sizeof(pSdp->aud.common.fingerprint)); } if(pSrtp) { pSdp->aud.common.transType = SDP_TRANS_TYPE_SRTP_SDES_UDP; if((rc = sdputil_initsrtp(&pSdp->aud.common.srtp, pSrtp)) < 0) { return rc; } } if(pStunCfg && pStunCfg->bindingRequest) { if(pStunCfg->reqUsername) { strncpy(pSdp->aud.common.ice.ufrag, pStunCfg->reqUsername, STUN_STRING_MAX - 1); } if(pStunCfg->reqPass) { strncpy(pSdp->aud.common.ice.pwd, pStunCfg->reqPass, STUN_STRING_MAX - 1); } } if(codecType == XC_CODEC_TYPE_AAC) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_AAC, sizeof(pSdp->aud.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_AMRNB) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_AMR, sizeof(pSdp->aud.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_SILK) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_SILK, sizeof(pSdp->aud.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_OPUS) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_OPUS, sizeof(pSdp->aud.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_G711_MULAW) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_PCMU, sizeof(pSdp->aud.common.encodingName)); } else if(codecType == XC_CODEC_TYPE_G711_ALAW) { strncpy(pSdp->aud.common.encodingName, SDP_RTPMAP_ENCODINGNAME_PCMA, sizeof(pSdp->aud.common.encodingName)); } break; case MEDIA_FILE_TYPE_MP2TS: pSdp->vid.common.available = 1; pSdp->vid.common.codecType = MEDIA_FILE_TYPE_MP2TS; pSdp->vid.common.payloadType = payloadType; pSdp->vid.common.port = dstPort; pSdp->vid.common.portRtcp = dstPortRtcp; pSdp->vid.common.clockHz = 90000; if(pSrtp) { pSdp->vid.common.transType = SDP_TRANS_TYPE_SRTP_SDES_UDP; if((rc = sdputil_initsrtp(&pSdp->vid.common.srtp, pSrtp)) < 0) { return rc; } } strncpy(pSdp->vid.common.encodingName, SDP_RTPMAP_ENCODINGNAME_MP2TS, sizeof(pSdp->vid.common.encodingName)); break; default: return -1; } // // Advertise any a=rtcp-fb: SDP flags // if(pSdp->vid.common.available) { if(pFbReq && (pFbReq->firCfg.fir_send_from_decoder || pFbReq->firCfg.fir_send_from_local || pFbReq->firCfg.fir_send_from_remote || pFbReq->firCfg.fir_send_from_capture)) { pSdp->vid.common.rtcpfb.fmtidmin1 = pSdp->vid.common.payloadType + 1; pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_CCM | SDP_RTCPFB_TYPE_CCM_FIR; } if(pFbReq && pFbReq->nackRtpRetransmit) { pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_NACK | SDP_RTCPFB_TYPE_NACK_GENERIC; } //pSdp->vid.common.rtcpfb.flags |= SDP_RTCPFB_TYPE_TRRINT; //pSdp->vid.common.rtcpfb.trrIntervalMs |= 30; } // // Codec specific default settings // switch(codecType) { case XC_CODEC_TYPE_H264: if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_PKTZMODE)) { switch(pCodecSpecific->u.pktzMode) { case PKTZ_H264_MODE_0: pSdp->vid.u.h264.packetization_mode = 0; break; case PKTZ_H264_MODE_2: LOG(X_WARNING("H.264 NAL Packetization mode 2 not supported. Using mode 1")); case PKTZ_H264_MODE_1: case PKTZ_H264_MODE_NOTSET: default: pSdp->vid.u.h264.packetization_mode = 1; break; } } break; case XC_CODEC_TYPE_MPEG4V: pSdp->vid.u.mpg4v.profile_level_id = 1; break; case XC_CODEC_TYPE_VP8: break; case XC_CODEC_TYPE_AAC: strncpy(pSdp->aud.u.aac.mode, "AAC-hbr", sizeof(pSdp->aud.u.aac.mode)); pSdp->aud.u.aac.sizelength = 13; pSdp->aud.u.aac.indexlength = 3; pSdp->aud.u.aac.indexdeltalength = 3; break; case XC_CODEC_TYPE_AMRNB: pSdp->aud.channels = 1; pSdp->aud.u.amr.octet_align = 1; break; case XC_CODEC_TYPE_SILK: if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_CHANNELS)) { pSdp->aud.channels = pCodecSpecific->u.channels; } else { pSdp->aud.channels = 1; } //pSdp->aud.u.silk.dummy = 0; break; case XC_CODEC_TYPE_OPUS: if(pCodecSpecific && (pCodecSpecific->flags & SDP_CODEC_PARAM_FLAGS_CHANNELS)) { pSdp->aud.channels = pCodecSpecific->u.channels;; } else { pSdp->aud.channels = 1; } break; case XC_CODEC_TYPE_G711_MULAW: case XC_CODEC_TYPE_G711_ALAW: pSdp->aud.channels = 1; break; default: break; } return rc; }
/* Returns: -1 = exit thread 1 = retry 0 = connected ok */ int connect_source(INPUT *r, int retries, int readbuflen, int *http_code) { CHANSRC *src = chansrc_init(r->channel->source); if (!src) { LOGf("ERR : Can't parse channel source | Channel: %s Source: %s\n", r->channel->name, r->channel->source); FATAL_ERROR; } r->connected = 0; r->reconnect = 0; int active = 1; int dret = async_resolve_host(src->host, src->port, &(r->src_sockname), 5000, &active); if (dret != 0) { if (dret == 1) proxy_log(r, "Can't resolve host"); if (dret == 2) proxy_log(r, "Timeout resolving host"); DO_RECONNECT; } proxy_log(r, "Connecting"); char buf[1024]; *http_code = 0; if (src->sproto == tcp_sock) { r->sock = socket(PF_INET, SOCK_STREAM, 0); if (r->sock < 0) { log_perror("play(): Could not create SOCK_STREAM socket.", errno); FATAL_ERROR; } //proxy_log(r, "Add"); if (do_connect(r->sock, (struct sockaddr *)&(r->src_sockname), sizeof(r->src_sockname), PROXY_CONNECT_TIMEOUT) < 0) { LOGf("ERR : Error connecting to %s srv_fd: %i err: %s\n", r->channel->source, r->sock, strerror(errno)); DO_RECONNECT; } snprintf(buf,sizeof(buf)-1, "GET /%s HTTP/1.0\nHost: %s:%u\nX-Smart-Client: yes\nUser-Agent: %s %s (%s)\n\n", src->path, src->host, src->port, server_sig, server_ver, config->ident); buf[sizeof(buf)-1] = 0; fdwrite(r->sock, buf, strlen(buf)); char xresponse[128]; memset(xresponse, 0, sizeof(xresponse)); memset(buf, 0, sizeof(buf)); regmatch_t res[4]; while (fdgetline(r->sock,buf,sizeof(buf)-1)) { if (buf[0] == '\n' || buf[0] == '\r') break; if (strstr(buf,"HTTP/1.") != NULL) { regex_t http_response; regcomp(&http_response, "^HTTP/1.[0-1] (([0-9]{3}) .*)", REG_EXTENDED); if (regexec(&http_response,buf,3,res,0) != REG_NOMATCH) { char codestr[4]; if ((unsigned int)res[1].rm_eo-res[1].rm_so < sizeof(xresponse)) { strncpy(xresponse, &buf[res[1].rm_so], res[1].rm_eo-res[1].rm_so); xresponse[res[1].rm_eo-res[1].rm_so] = '\0'; chomp(xresponse); strncpy(codestr, &buf[res[2].rm_so], res[2].rm_eo-res[2].rm_so); codestr[3] = 0; *http_code = atoi(codestr); } } regfree(&http_response); } if (*http_code == 504) { // Extract extra error code if (strstr(buf, "X-ErrorCode: ") != NULL) { *http_code = atoi(buf+13); break; } } } if (*http_code == 0) { // No valid HTTP response, retry LOGf("DEBUG: Server returned not valid HTTP code | srv_fd: %i\n", r->sock); DO_RECONNECT; } if (*http_code == 504) { // No signal, exit LOGf("ERR : Get no-signal for %s from %s on srv_fd: %i\n", r->channel->name, r->channel->source, r->sock); FATAL_ERROR; } if (*http_code > 300) { // Unhandled or error codes, exit LOGf("ERR : Get code %i for %s from %s on srv_fd: %i exiting.\n", *http_code, r->channel->name, r->channel->source, r->sock); FATAL_ERROR; } // connected ok, continue } else { if (!IN_MULTICAST(ntohl(r->src_sockname.sin_addr.s_addr))) { LOGf("ERR : %s is not multicast address\n", r->channel->source); FATAL_ERROR; } struct ip_mreq mreq; struct sockaddr_in receiving_from; r->sock = socket(PF_INET, SOCK_DGRAM, 0); if (r->sock < 0) { log_perror("play(): Could not create SOCK_DGRAM socket.", errno); FATAL_ERROR; } // LOGf("CONN : Listening on multicast socket %s srv_fd: %i retries left: %i\n", r->channel->source, r->sock, retries); int on = 1; setsockopt(r->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); // subscribe to multicast group memcpy(&mreq.imr_multiaddr, &(r->src_sockname.sin_addr), sizeof(struct in_addr)); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(r->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { LOGf("ERR : Failed to add IP membership on %s srv_fd: %i\n", r->channel->source, r->sock); FATAL_ERROR; } // bind to the socket so data can be read memset(&receiving_from, 0, sizeof(receiving_from)); receiving_from.sin_family = AF_INET; receiving_from.sin_addr = r->src_sockname.sin_addr; receiving_from.sin_port = htons(src->port); if (bind(r->sock, (struct sockaddr *) &receiving_from, sizeof(receiving_from)) < 0) { LOGf("ERR : Failed to bind to %s srv_fd: %i\n", r->channel->source, r->sock); FATAL_ERROR; } } if (setsockopt(r->sock, SOL_SOCKET, SO_RCVBUF, (const char *)&readbuflen, sizeof(readbuflen)) < 0) log_perror("play(): setsockopt(SO_RCVBUF)", errno); r->connected = 1; // proxy_log(r, "Connected"); chansrc_free(&src); return 0; }
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; memset(p, 0, sizeof(*p)); memset(&medium, 0, sizeof(medium)); p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_GRE; } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; } else { fprintf(stderr,"Cannot guess tunnel mode.\n"); exit(-1); } } else if (strcmp(*argv, "key") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"key\"\n"); exit(-1); } p->i_key = p->o_key = htonl(uval); } } else if (strcmp(*argv, "ikey") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"ikey\"\n"); exit(-1); } p->i_key = htonl(uval); } } else if (strcmp(*argv, "okey") == 0) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"okey\"\n"); exit(-1); } p->o_key = htonl(uval); } } else if (strcmp(*argv, "seq") == 0) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "iseq") == 0) { p->i_flags |= GRE_SEQ; } else if (strcmp(*argv, "oseq") == 0) { p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "csum") == 0) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "icsum") == 0) { p->i_flags |= GRE_CSUM; } else if (strcmp(*argv, "ocsum") == 0) { p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "nopmtudisc") == 0) { p->iph.frag_off = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.daddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.saddr = get_addr32(*argv); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ-1); } else if (strcmp(*argv, "ttl") == 0) { unsigned uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <=255\n", *argv); p->iph.ttl = uval; } } else if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); p->iph.tos = uval; } else p->iph.tos = 1; } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; } if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { fprintf(stderr, "Keys are not allowed with ipip and sit.\n"); return -1; } } if (medium[0]) { p->link = tnl_ioctl_get_ifindex(medium); if (p->link == 0) return -1; } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { fprintf(stderr, "Broadcast tunnel requires a source address.\n"); return -1; } return 0; }
/* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ipintr() { register struct ip *ip; register struct mbuf *m; register struct ipq *fp; register struct in_ifaddr *ia; int hlen, s; next: /* * Get next datagram off input queue and get IP header * in first mbuf. */ s = splimp(); IF_DEQUEUE(&ipintrq, m); splx(s); if (m == 0) return; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ipintr no HDR"); #endif /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ if (in_ifaddr == NULL) goto bad; ipstat.ips_total++; if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; goto next; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { ipstat.ips_badvers++; goto bad; } hlen = ip->ip_hl << 2; if (hlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; goto bad; } if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_badhlen++; goto next; } ip = mtod(m, struct ip *); } if (ip->ip_sum = in_cksum(m, hlen)) { ipstat.ips_badsum++; goto bad; } /* * Convert fields to host representation. */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { ipstat.ips_badlen++; goto bad; } NTOHS(ip->ip_id); NTOHS(ip->ip_off); /* * Check that the amount of data in the buffers * is as at least much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < ip->ip_len) { ipstat.ips_tooshort++; goto bad; } if (m->m_pkthdr.len > ip->ip_len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = ip->ip_len; m->m_pkthdr.len = ip->ip_len; } else m_adj(m, ip->ip_len - m->m_pkthdr.len); } /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) goto next; /* * Check our list of addresses, to see if the packet is for us. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) { #define satosin(sa) ((struct sockaddr_in *)(sa)) if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if ( #ifdef DIRECTED_BROADCAST ia->ia_ifp == m->m_pkthdr.rcvif && #endif (ia->ia_ifp->if_flags & IFF_BROADCAST)) { u_long t; if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) goto ours; /* * Look for all-0's host part (old broadcast addr), * either for subnet or net. */ t = anp_sys_ntohl(ip->ip_dst.s_addr); if (t == ia->ia_subnet) goto ours; if (t == ia->ia_net) goto ours; } } if (IN_MULTICAST(anp_sys_ntohl(ip->ip_dst.s_addr))) { struct in_multi *inm; #ifdef MROUTING extern struct socket *ip_mrouter; if (ip_mrouter) { /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. * * (The IP ident field is put in the same byte order * as expected when ip_mforward() is called from * ip_output().) */ ip->ip_id = anp_sys_htons(ip->ip_id); if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) { ipstat.ips_cantforward++; m_freem(m); goto next; } ip->ip_id = anp_sys_ntohs(ip->ip_id); /* * The process-level routing demon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) goto ours; ipstat.ips_forward++; } #endif /* * See if we belong to the destination multicast group on the * arrival interface. */ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); if (inm == NULL) { ipstat.ips_cantforward++; m_freem(m); goto next; } goto ours; } if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) goto ours; if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; /* * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { ipstat.ips_cantforward++; m_freem(m); } else ip_forward(m, 0); goto next; ours: /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ IP_DF) { if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; goto next; } ip = mtod(m, struct ip *); } /* * Look for queue of fragments * of this datagram. */ for (fp = ipq.next; fp != &ipq; fp = fp->next) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; fp = 0; found: /* * Adjust ip_len to not reflect header, * set ip_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len -= hlen; ((struct ipasfrag *)ip)->ipf_mff &= ~1; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { ipstat.ips_fragments++; ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) goto next; ipstat.ips_reassembled++; m = dtom(ip); } else if (fp) ip_freef(fp); } else
static int geneve_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 vni = 0; int vni_set = 0; __u32 daddr = 0; struct in6_addr daddr6 = IN6ADDR_ANY_INIT; __u32 label = 0; __u8 ttl = 0; __u8 tos = 0; __u16 dstport = 0; bool metadata = 0; __u8 udpcsum = 0; bool udpcsum_set = false; __u8 udp6zerocsumtx = 0; bool udp6zerocsumtx_set = false; __u8 udp6zerocsumrx = 0; bool udp6zerocsumrx_set = false; while (argc > 0) { if (!matches(*argv, "id") || !matches(*argv, "vni")) { NEXT_ARG(); if (get_u32(&vni, *argv, 0) || vni >= 1u << 24) invarg("invalid id", *argv); vni_set = 1; } else if (!matches(*argv, "remote")) { NEXT_ARG(); if (!inet_get_addr(*argv, &daddr, &daddr6)) { fprintf(stderr, "Invalid address \"%s\"\n", *argv); return -1; } if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) invarg("invalid remote address", *argv); } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { unsigned int uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL", *argv); if (uval > 255) invarg("TTL must be <= 255", *argv); ttl = uval; } } else if (!matches(*argv, "tos") || !matches(*argv, "dsfield")) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (!matches(*argv, "label") || !matches(*argv, "flowlabel")) { __u32 uval; NEXT_ARG(); if (get_u32(&uval, *argv, 0) || (uval & ~LABEL_MAX_MASK)) invarg("invalid flowlabel", *argv); label = htonl(uval); } else if (!matches(*argv, "dstport")) { NEXT_ARG(); if (get_u16(&dstport, *argv, 0)) invarg("dstport", *argv); } else if (!matches(*argv, "external")) { metadata = true; } else if (!matches(*argv, "noexternal")) { metadata = false; } else if (!matches(*argv, "udpcsum")) { udpcsum = 1; udpcsum_set = true; } else if (!matches(*argv, "noudpcsum")) { udpcsum = 0; udpcsum_set = true; } else if (!matches(*argv, "udp6zerocsumtx")) { udp6zerocsumtx = 1; udp6zerocsumtx_set = true; } else if (!matches(*argv, "noudp6zerocsumtx")) { udp6zerocsumtx = 0; udp6zerocsumtx_set = true; } else if (!matches(*argv, "udp6zerocsumrx")) { udp6zerocsumrx = 1; udp6zerocsumrx_set = true; } else if (!matches(*argv, "noudp6zerocsumrx")) { udp6zerocsumrx = 0; udp6zerocsumrx_set = true; } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "geneve: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } if (metadata && vni_set) { fprintf(stderr, "geneve: both 'external' and vni cannot be specified\n"); return -1; } if (!metadata) { /* parameter checking make sense only for full geneve tunnels */ if (!vni_set) { fprintf(stderr, "geneve: missing virtual network identifier\n"); return -1; } if (!daddr && IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { fprintf(stderr, "geneve: remote link partner not specified\n"); return -1; } } addattr32(n, 1024, IFLA_GENEVE_ID, vni); if (daddr) addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4); if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6)) addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6, sizeof(struct in6_addr)); addattr32(n, 1024, IFLA_GENEVE_LABEL, label); addattr8(n, 1024, IFLA_GENEVE_TTL, ttl); addattr8(n, 1024, IFLA_GENEVE_TOS, tos); if (dstport) addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport)); if (metadata) addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA); if (udpcsum_set) addattr8(n, 1024, IFLA_GENEVE_UDP_CSUM, udpcsum); if (udp6zerocsumtx_set) addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, udp6zerocsumtx); if (udp6zerocsumrx_set) addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, udp6zerocsumrx); return 0; }
int lwes_net_open (struct lwes_net_connection *conn, const char *address, const char *iface, int port) { struct in_addr validated_address; struct in_addr validated_iface; /* error out on a NULL connection */ if (conn == NULL) { return -1; } /* validate the arguments */ if (inet_aton (address, &validated_address) == 0) { return -2; } if (iface != NULL && inet_aton (iface, &validated_iface) == 0) { return -3; } /* set up the address structure */ memset((char *) &conn->ip_addr, 0, sizeof(conn->ip_addr)); conn->ip_addr.sin_family = AF_INET; conn->ip_addr.sin_addr = validated_address; conn->ip_addr.sin_port = htons ((short)port); conn->has_bound = 0; conn->has_joined = 0; if (IN_MULTICAST (ntohl (conn->ip_addr.sin_addr.s_addr))) { conn->is_multicast = 1; } else { conn->is_multicast = 0; } /* construct the socket */ if ( (conn->socketfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0 ) { return -4; } if (conn->is_multicast) { /* if the address we are emitting on is a multicast address we set the sockopt which uses that interface to emit on, this doesn't work for unicast */ conn->mreq.imr_multiaddr = conn->ip_addr.sin_addr; if (iface != NULL) { conn->mreq.imr_interface = validated_iface; if (setsockopt(conn->socketfd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&validated_iface, sizeof(validated_iface)) < 0 ) { return -5; } } else { conn->mreq.imr_interface.s_addr = htonl (INADDR_ANY); } } /* Setting the value for SO_SNDBF , trying for 10*MAX_MSG_SIZE */ int i; for ( i = 10 ; i > 0 ; i-- ) { int sndbufsize = MAX_MSG_SIZE*i; if (setsockopt (conn->socketfd, SOL_SOCKET, SO_SNDBUF, (void*)&sndbufsize,sizeof(sndbufsize)) == 0) { break; } } if ( i == 0 ) { return -6; } /* set the size for use below */ conn->sender_ip_socket_size = (socklen_t)sizeof(conn->sender_ip_addr); return 0; }
int igmpv3_accept(int recvlen, struct IfDesc *dp) { register __u32 src, dst, group; struct iphdr *ip; struct igmphdr *igmp; int ipdatalen, iphdrlen; struct mcft_entry *mymcp; if (recvlen < sizeof(struct iphdr)) { log(LOG_WARNING, 0, "received packet too short (%u bytes) for IP header", recvlen); return 0; } ip = (struct iphdr *)recv_buf; src = ip->saddr; dst = ip->daddr; if(!IN_MULTICAST(dst)) /* It isn't a multicast */ return -1; if(chk_local(src)) /* It's our report looped back */ return -1; if(dst == ALL_PRINTER) /* It's MS-Windows UPNP all printers notify */ return -1; //pkt_debug(recv_buf); iphdrlen = ip->ihl << 2; ipdatalen = ip->tot_len; igmp = (struct igmphdr *)(recv_buf + iphdrlen); group = igmp->group; /* determine message type */ IGMPV3LOG("\n%s> receive IGMP type [%x] from %s to ", __FUNCTION__, igmp->type, inet_ntoa(ip->saddr)); IGMPV3LOG("%s\n", inet_ntoa(ip->daddr)); switch (igmp->type) { case IGMP_HOST_MEMBERSHIP_QUERY: /* Linux Kernel will process local member query, it wont reach here */ break; case IGMP_HOST_MEMBERSHIP_REPORT: #ifdef CONFIG_DEFAULTS_KERNEL_2_6 case IGMPV2_HOST_MEMBERSHIP_REPORT: #else case IGMP_HOST_NEW_MEMBERSHIP_REPORT: #endif { IGMPV3LOG("%s> REPORT(V1/V2), group:%s\n", __FUNCTION__, inet_ntoa(group) ); if(!chk_mcft(group)) { mymcp = add_mcft(group, src); if(!mymcp) return -1; mymcp->igmp_ver = IGMP_VER_2; igmp_add_group( group ); //Group Timer=GMI mymcp->timer.lefttime = MEMBER_QUERY_INTERVAL; mymcp->timer.retry_left = MEMBER_QUERY_COUNT; //set the new state mymcp->filter_mode = MCAST_EXCLUDE; igmp_set_srcfilter( mymcp ); } mymcp = get_mcft(group); if(mymcp) mymcp->igmp_ver = IGMP_VER_2; //Report => IS_EX( {} ) handle_igmpv3_isex( group,src, 0, NULL ); } break; case IGMP_HOST_V3_MEMBERSHIP_REPORT: { struct igmpv3_report *igmpv3; struct igmpv3_grec *igmpv3grec; unsigned short rec_id; IGMPV3LOG("%s> REPORT(V3)\n", __FUNCTION__ ); igmpv3 = (struct igmpv3_report *)igmp; //printf( "recv IGMP_HOST_V3_MEMBERSHIP_REPORT\n" ); //printf( "igmpv3->type:0x%x\n", igmpv3->type ); //printf( "igmpv3->ngrec:0x%x\n\n", ntohs(igmpv3->ngrec) ); rec_id=0; igmpv3grec = &igmpv3->grec[0]; while( rec_id < ntohs(igmpv3->ngrec) ) { int srcnum; //printf( "igmpv3grec[%d]->grec_type:0x%x\n", rec_id, igmpv3grec->grec_type ); //printf( "igmpv3grec[%d]->grec_auxwords:0x%x\n", rec_id, igmpv3grec->grec_auxwords ); //printf( "igmpv3grec[%d]->grec_nsrcs:0x%x\n", rec_id, ntohs(igmpv3grec->grec_nsrcs) ); //printf( "igmpv3grec[%d]->grec_mca:%s\n", rec_id, inet_ntoa(igmpv3grec->grec_mca) ); group = igmpv3grec->grec_mca; srcnum = ntohs(igmpv3grec->grec_nsrcs); switch( igmpv3grec->grec_type ) { case IGMPV3_MODE_IS_INCLUDE: IGMPV3LOG("%s> IS_IN, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_isin( group,src, srcnum, igmpv3grec->grec_src ); break; case IGMPV3_MODE_IS_EXCLUDE: IGMPV3LOG("%s> IS_EX, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_isex( group,src, srcnum, igmpv3grec->grec_src ); break; case IGMPV3_CHANGE_TO_INCLUDE: IGMPV3LOG("%s> TO_IN, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_toin( group,src, srcnum, igmpv3grec->grec_src ); break; case IGMPV3_CHANGE_TO_EXCLUDE: IGMPV3LOG("%s> TO_EX, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_toex( group,src, srcnum, igmpv3grec->grec_src ); break; case IGMPV3_ALLOW_NEW_SOURCES: IGMPV3LOG("%s> ALLOW, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_allow( group,src, srcnum, igmpv3grec->grec_src ); break; case IGMPV3_BLOCK_OLD_SOURCES: IGMPV3LOG("%s> BLOCK, group:%s, srcnum:%d\n", __FUNCTION__, inet_ntoa(group), srcnum ); handle_igmpv3_block( group,src, srcnum, igmpv3grec->grec_src ); break; default: IGMPV3LOG("%s> Unknown Group Record Types [%x]\n", __FUNCTION__, igmpv3grec->grec_type ); break; } rec_id++; //printf( "count next: 0x%x %d %d %d %d\n", igmpv3grec, sizeof( struct igmpv3_grec ), igmpv3grec->grec_auxwords, ntohs(igmpv3grec->grec_nsrcs), sizeof( __u32 ) ); igmpv3grec = (struct igmpv3_grec *)( (char*)igmpv3grec + sizeof( struct igmpv3_grec ) + (igmpv3grec->grec_auxwords+ntohs(igmpv3grec->grec_nsrcs))*sizeof( __u32 ) ); //printf( "count result: 0x%x\n", igmpv3grec ); } break; } case IGMP_HOST_LEAVE_MESSAGE : IGMPV3LOG("%s> LEAVE(V2), group:%s\n", __FUNCTION__, inet_ntoa(group) ); if(chk_mcft(group)) { //Leave => TO_IN( {} ) handle_igmpv3_toin( group,src, 0, NULL ); } break; default: IGMPV3LOG("%s> receive IGMP Unknown type [%x]\n", __FUNCTION__, igmp->type ); break; } return 0; }
/* * Set IPv4 source filter list in use on socket. * * Stubbed to setsourcefilter(). Performs conversion of structures which * may be inefficient; applications are encouraged to use the * protocol-independent API. */ int setipv4sourcefilter(int s, struct in_addr interface, struct in_addr group, uint32_t fmode, uint32_t numsrc, struct in_addr *slist) { #ifdef INET sockunion_t tmpgroup; struct in_addr *pina; sockunion_t *psu, *tmpslist; int err; size_t i; uint32_t ifindex; assert(s != -1); tmpslist = NULL; if (!IN_MULTICAST(ntohl(group.s_addr)) || (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE)) { errno = EINVAL; return (-1); } ifindex = __inaddr_to_index(interface.s_addr); if (ifindex == 0) { errno = EADDRNOTAVAIL; return (-1); } memset(&tmpgroup, 0, sizeof(sockunion_t)); tmpgroup.sin.sin_family = AF_INET; tmpgroup.sin.sin_len = sizeof(struct sockaddr_in); tmpgroup.sin.sin_addr = group; if (numsrc != 0 || slist != NULL) { tmpslist = calloc(numsrc, sizeof(sockunion_t)); if (tmpslist == NULL) { errno = ENOMEM; return (-1); } pina = slist; psu = tmpslist; for (i = 0; i < numsrc; i++, pina++, psu++) { psu->sin.sin_family = AF_INET; psu->sin.sin_len = sizeof(struct sockaddr_in); psu->sin.sin_addr = *pina; } } err = setsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup, sizeof(struct sockaddr_in), fmode, numsrc, (struct sockaddr_storage *)tmpslist); if (tmpslist != NULL) free(tmpslist); return (err); #else /* !INET */ return (EAFNOSUPPORT); #endif /* INET */ }
/* * Parallel to llc_rtrequest. */ static void arp_rtrequest( int req, struct rtentry *rt, __unused struct sockaddr *sa) { struct sockaddr *gate = rt->rt_gateway; struct llinfo_arp *la = rt->rt_llinfo; static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK, 0, 0, 0, 0, 0, {0}}; struct timeval timenow; if (!arpinit_done) { panic("%s: ARP has not been initialized", __func__); /* NOTREACHED */ } lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED); RT_LOCK_ASSERT_HELD(rt); if (rt->rt_flags & RTF_GATEWAY) return; getmicrotime(&timenow); switch (req) { case RTM_ADD: /* * XXX: If this is a manually added route to interface * such as older version of routed or gated might provide, * restore cloning bit. */ if ((rt->rt_flags & RTF_HOST) == 0 && SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) rt->rt_flags |= RTF_CLONING; if (rt->rt_flags & RTF_CLONING) { /* * Case 1: This route should come from a route to iface. */ if (rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl) == 0) { gate = rt->rt_gateway; SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; /* * In case we're called before 1.0 sec. * has elapsed. */ rt->rt_expire = MAX(timenow.tv_sec, 1); } break; } /* Announce a new entry if requested. */ if (rt->rt_flags & RTF_ANNOUNCE) { RT_UNLOCK(rt); dlil_send_arp(rt->rt_ifp, ARPOP_REQUEST, SDL(gate), rt_key(rt), NULL, rt_key(rt)); RT_LOCK(rt); } /*FALLTHROUGH*/ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(null_sdl)) { if (log_arp_warnings) log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); break; } SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; if (la != 0) break; /* This happens on a route change */ /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ rt->rt_llinfo = la = arp_llinfo_alloc(); if (la == NULL) { if (log_arp_warnings) log(LOG_DEBUG, "%s: malloc failed\n", __func__); break; } rt->rt_llinfo_free = arp_llinfo_free; arp_inuse++, arp_allocated++; Bzero(la, sizeof(*la)); la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; LIST_INSERT_HEAD(&llinfo_arp, la, la_le); /* * This keeps the multicast addresses from showing up * in `arp -a' listings as unresolved. It's not actually * functional. Then the same for broadcast. */ if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) { RT_UNLOCK(rt); dlil_resolve_multi(rt->rt_ifp, rt_key(rt), gate, sizeof(struct sockaddr_dl)); RT_LOCK(rt); rt->rt_expire = 0; } else if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { struct sockaddr_dl *gate_ll = SDL(gate); size_t broadcast_len; ifnet_llbroadcast_copy_bytes(rt->rt_ifp, LLADDR(gate_ll), sizeof(gate_ll->sdl_data), &broadcast_len); gate_ll->sdl_alen = broadcast_len; gate_ll->sdl_family = AF_LINK; gate_ll->sdl_len = sizeof(struct sockaddr_dl); /* In case we're called before 1.0 sec. has elapsed */ rt->rt_expire = MAX(timenow.tv_sec, 1); } if (SIN(rt_key(rt))->sin_addr.s_addr == (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed local traffic to be forced * through the hardware by configuring the loopback down. * However, it causes problems during network configuration * for boards that can't receive packets they send. * It is now necessary to clear "useloopback" and remove * the route to force traffic out to the hardware. */ rt->rt_expire = 0; ifnet_lladdr_copy_bytes(rt->rt_ifp, LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); if (useloopback) { #if IFNET_ROUTE_REFCNT /* Adjust route ref count for the interfaces */ if (rt->rt_if_ref_fn != NULL && rt->rt_ifp != lo_ifp) { rt->rt_if_ref_fn(lo_ifp, 1); rt->rt_if_ref_fn(rt->rt_ifp, -1); } #endif /* IFNET_ROUTE_REFCNT */ rt->rt_ifp = lo_ifp; } } break; case RTM_DELETE: if (la == 0) break; arp_inuse--; /* * Unchain it but defer the actual freeing until the route * itself is to be freed. rt->rt_llinfo still points to * llinfo_arp, and likewise, la->la_rt still points to this * route entry, except that RTF_LLINFO is now cleared. */ LIST_REMOVE(la, la_le); la->la_le.le_next = NULL; la->la_le.le_prev = NULL; rt->rt_flags &= ~RTF_LLINFO; if (la->la_hold != NULL) m_freem(la->la_hold); la->la_hold = NULL; } }