Пример #1
0
/*
 * 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);
}
Пример #2
0
/* 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");
	}
}
Пример #3
0
/*
 * 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;
}
Пример #4
0
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;
}
Пример #6
0
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;
		}
	}
}
Пример #7
0
/**
*   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;
}
Пример #8
0
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 */
Пример #9
0
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;
    }
    
}
Пример #10
0
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");
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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);
}
Пример #14
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;
}
Пример #15
0
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;
		}
	}
}
Пример #16
0
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;
}
Пример #17
0
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;
		}
	}
}
Пример #18
0
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;
}
Пример #19
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;
		}
	}
}
Пример #20
0
/*
 * 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 */
Пример #21
0
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);
}
Пример #22
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;
}
Пример #23
0
/*
	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;
}
Пример #24
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;
}
Пример #25
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
Пример #26
0
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;
}
Пример #27
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;
}
Пример #28
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;
}
Пример #29
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 */
}
Пример #30
0
/*
 * 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;
	}
}